可复用构件设计的原则

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

论文

题目:可复用构件设计的原则

院(系): 研究生学院

专业年级: 计算机科学与技术

**: ***

学号: *********

****: ***

2014年4月29日

一、开闭原则

1988年,Bertrand Meyer在他的著作《Object Oriented Software Construction》中提出了开闭原则,原文为:“Software entities should be open for extension,but closed for modification”。即“软件实体应当对扩展开放,对修改关闭”。即软件系统中包含的各种组件,例如模块(Modules)、类(Classes)以及功能(Functions)等等,应该在不修改现有代码的基础上,引入新功能。开闭原则中的“开”,是指对于组件功能的扩展是开放的,是允许对其进行功能扩展的;开闭原则中的“闭”,是指对于原有代码的修改是封闭的,即不应该修改原有的代码。

实现开闭原则的关键就在于“抽象”。把系统的所有可能的行为抽象成一个抽象底层,这个抽象底层规定出所有的具体实现必须提供的方法的特征。作为系统设计的抽象层,要预见所有可能的扩展,从而使得在任何扩展情况下,系统的抽象底层不需修改;同时,由于可以从抽象底层导出一个或多个新的具体实现,可以改变系统的行为,因此系统设计对扩展是开放的。

在软件开发的过程中,一直都是提倡需求导向的。这就要求在设计的时候,要非常清楚地了解用户需求,判断需求中包含的可能的变化,从而明确在什么情况下使用开闭原则。

关于系统可变的部分,还有一个更具体的原则是对可变性的封装原则(Principle of Encapsulation of Variation, EVP),它从软件工程实现的角度对开闭原则进行了进一步的解释。EVP要求在做系统设计的时候,对系统所有可能发生变化的部分进行评估和分类,每一个可变的因素都单独进行封装。“对可变性的封装原则”意味着两点:

(1)一种可变性不应当散落在代码的很多角落里,而应当被封装到一个对象里面。同一种可变性的不同表象意味着同一个继承等级结构中的具体子类,因此,我们可以期待在设计模式中看到继承关系。继承应当被看做是封装变化的方法,而不应当被认为是从一般的对象生成特殊的对象的方法。

(2)一种可变性不应当与另一种可变性混合在一起。

在实际开发过程的设计开始阶段,就要罗列出来系统所有可能的行为,并把这些行为加入到抽象底层,根本就是不可能的,这么去做也是不经济的,费时费力。另外,在设计开始阶段,对所有的可变因素进行预计和封装也不太现实,也是很难做得到。所以,开闭原则描绘的蓝图只是一种理想情况或是极端状态,现实世界中是很难被完全实现的。只能在某些组件,在某种程度上符合开闭原则的要求。

开闭原则具有理想主义的色彩,它是面向对象设计的终极目标。因此,针对开闭原则的实现方法,一直都有面向对象设计的大师费尽心机,研究开闭原则的

实现方式。其它原则和方法如:里氏代换原则、依赖倒转原则、接口隔离原则以及抽象类、接口等等,都可以看作是开闭原则的实现方法。

二、里氏代换原则

里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。根据里氏代换原则,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

LSP介绍的是基类和子类的关系。只有当这种关系存在时,里氏代换关系才存在。如果两个具体的类A,B之间的关系违反了LSP的设计,(假设是从B到A 的继承关系)那么根据具体的情况可以在下面的两种重构方案中选择一种。

-----创建一个新的抽象类C,作为两个具体类的超类,将A,B的共同行为移动到C中来解决问题。

-----从B到A的继承关系改为委派关系。

三、依赖倒置原则

依赖倒置原则有如下定义:1)上层模块不应该依赖于底层模块,它们都应该依赖于抽象。2)抽象不应该依赖于细节,细节应该依赖于抽象,要针对接口编程,不要针对实现编程。

依赖倒置原则虽然很强大,但却最不容易实现。因为依赖倒置的缘故,对象的创建很可能要使用对象工厂,以避免对具体类的直接引用,此原则的使用可能还会导致产生大量的类,对不熟悉面向对象技术的工程师来说,维护这样的系统需要较好地理解面向对象设计。

依赖倒置原则假定所有的具体类都是会变化的,这也不总是正确。有一些具体类可能是相当稳定,不会变化的,使用这个具体类实例的应用完全可以依赖于这个具体类型,而不必为此创建一个抽象类型。

四、接口隔离原则

接口隔离原则的含义是一个指导可复用构件中实体接口设计的原则,它使得构件中每个实体都拥有尽可能简单的接口。实现的策略应该是针对不同的使用者提供不同的接口,也就是定制服务的思想。做法是对构件中每个实体的使用者进行角色划分,然后针对每一类使用者提供一套有针对性的接口。即变一个大而全的接口为多个简单有针对性的接口,减少需求变更引发的维护问题

五、合成/聚合复用原则

合成/聚合复用原则是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向这些对象的委派达到复用这些对象的目的。首先使用合成/聚合,合成/聚合则使系统灵活,其次才考虑继承,达到复用的目的。而使用继承时,要严格遵循里氏代换原则。有效地使用继承会有助于对问题的理解,降低复杂度,而滥用继承会增加系统构建、维护时的难度及系统的复杂度。如果两个类是“Has-a”关系应使用合成、聚合,如果是“Is-a”关系可使用继承。“Is-A”是严格的分类学意义上定义,意思是一个类是另一个类的“一种”。而“Has-A”则不同,它表示某一个角色具有某一项责任。

通过合成/聚合来进行复用的优点有:1、新对象存取成分对象的唯一方法是通过成分对象的接口。2、这种复用是黑箱复用,因为成分对象的内部细节是新对象所看不见的。3、这种复用支持包装。4、这种复用所需的依赖较少。5、每一个新的类可以将焦点集中在一个任务上。6、这种复用可以在运行时间内动态进行,新对象可以动态的引用与成分对象类型相同的对象。7、作为复用手段可以应用到几乎任何环境中去。缺点就是系统中会有较多的对象需要管理。

六、迪米特法则

迪米特法则指的是一个软件实体应当尽可能少的与其他实体发生相互作用。这样,当一个模块修改时,就会尽量少的影响其他的模块。扩展会相对容易。这是对软件实体之间通信的限制。它要求限制软件实体之间通信的宽度和深度。迪米特法则还有其他表述,例如只与你直接的朋友们通信,不要跟“陌生人”说话,每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。

狭义的迪米特法则是指如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中的一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

狭义的迪米特法则的缺点是在系统里造出大量的小方法,这些方法仅仅是传递间接的调用,与系统的商务逻辑无关。遵循类之间的迪米特法则会是一个系统的局部设计简化,因为每一个局部都不会和远距离的对象有直接的关联。但是,这也会造成系统的不同模块之间的通信效率降低,也会使系统的不同模块之间不容易协调。门面(外观)模式和调停者(中介者)模式实际上就是迪米特法则的具体应用。

广义的迪米特法则迪米特法则的主要用意是控制信息的过载。在将迪米特法则运用到系统设计中时,要注意下面的几点:

相关文档
最新文档