设计模式对系统设计与实现的影响-(2)

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

1引言

从上世纪60年代末开始,由于计算机软件对生产力有巨大的推动作用,各种大型、复杂的软件系统相继被开发出来。然而,随着软件系统规模的扩大和复杂性的增加,软件开发对人力、物力的需求越来越大,同时软件系统的可靠性和可维护性明显降低,软件行业出现了危机。直到80年代,软件开发采用面向对象设计思想和开发技术,软件危机才在一定程度上得到缓解。面向对象开发方法的核心思想是将系统看成是对象及对象之间的相互关系的集合,思维方式更接近人类认识世界的规律,克服了面向过程开发存在的诸多弊端。但是采用面向对象的方法来开发软件也需要一些正确的开发原则来指导,否则,开发的软件将不可避免地带有某些缺陷,如系统过于僵硬,不能很好地适应需求变化;系统过于脆弱,往往修改一处代码会带来无法预测的后果;系统复用率低,黏度过高等等。为了避免上述缺陷,设计出具备良好的可扩展性、可复用性、易维护性的系统,我们应在系统设计和实践阶段采用设计模式的思想。

设计模式是软件复用技术中的一个重要概念[1]。它是指以文档的形式把面向对象的软件设计经验记录下来,并予以系统的命名、解释和评价,使不同的开发人员在进行不同系统的设计与开发时,可以使用别人的成功经验而不必为普通的、重复的问题重新设计解决方案,使设计者更容易理解其设计思路,能为自己的问题找到更适合的解决办法,更快更好地完成系统设计。随着技术的不断完善,设计模式的种类日益增多,相对于GoF在1994年提出的23种通用设计模式,数量已大大增加。选择适合自己系统的模式对系统的设计与实现都至关重要,当对各种模式有足够全面的了解时,许多设计决策就自然而然产生了。为了研究设计模式是如何影响系统设计与实现的,应结合面向对象设计原则和软件工程思想来进行探讨[2]。

2 从设计原则到设计模式

2.1 设计原则

我们之所以提倡设计模式,就是为了代码复用,增强系统的可维护性。面向对象有几个原则:开闭原则、里氏代换原则、依赖倒转原则、接口隔离原则、合成/聚合复用原则、最小知识原则、单一职责原则和抽象原则。开闭原则具有理

想主义色彩,它是面向对象设计的终极目标。其他几条,则可以看做是开闭原则的实现方法。设计模式就是实现了这些原则,从而达到了代码复用、增加可维护性的目的。

(1)开闭原则

一个软件实体应当对扩展开放,对修改关闭。开闭原则是面向对象设计中最基础的设计原则,它指导我们如何建立稳定灵活的系统。我们在重构代码时尽量在不修改原来代码的情况下进行扩展。这样在扩展的同时对旧版本有很好的支持,使得系统更加灵活,具有很强的适应性。

(2)里氏代换原则

子类可以扩展父类的功能,但不能改变父类原有的功能。父类中凡是已经实现好的方法(相对于抽象方法而言),实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些契约,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。

继承作为面向对象三大特性之一,在给程序设计带来巨大便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加了对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能会产生故障。在模块中应当尽量从抽象类中继承,而不是从具体的类中继承。里氏替换是软件代码复用的重要基础。

(3)合成复用原则

合成是值的聚合,聚合是引用的聚合。合成和聚合都是关联的特殊种类,聚合表示整体和部分的关系,表示“拥有”;合成则是一种更强的“拥有”,部分和整体的生命周期是一样的,合成的新的对象完全支配其组成部分,包括他们的创建和湮灭。一个合成关系的成分对象是不能与另一个合成关系共享的。我们在开发中应尽量使用合成/聚合,而不是使用继承。

(4)依赖倒转原则

依赖倒置原则的核心思想是面向接口编程。要针对接口编程,不要针对实现编程;传递参数,或者在组合聚合关系中,尽量引用层次高的类。高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖于细节,细节应该依赖于抽象。程序在需要引用一个对象时,应当尽可能的使用抽象类型作为变量的

静态方法,即面向接口编程,是达到开闭原则的途径。针对接口编程和抽象类就是要做到一个具体的类应当只实现类的接口和抽象类中声明的方法,而没有多余的方法。依赖倒置原则基于这样一个事实:相对于细节的多变性,抽象的东西要稳定得多。以抽象为基础搭建起来的架构比以细节为基础搭建起来的架构要稳定得多。使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。

(5)接口隔离原则

客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法应尽量少。我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。在程序设计中,依赖几个专用的接口要比依赖一个综合的接口更灵活。接口是设计时对外部设定的“契约”,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。在面向对象设计时恰当地划分角色和角色对应的接口是非常重要的。将没有关系的接口合并在一起是对角色和接口的污染。原则要求我们不同的角色要给不同的接口,而不能交给一个接口。

(6)抽象原则

用抽象构建框架,用实现扩展细节。因为抽象灵活性好,适应性广,只要抽象得合理,可以基本保持软件架构的稳定。而软件中易变的细节,我们用从抽象派生的实现类来进行扩展,当软件需要发生变化时,我们只需要根据需求重新派生一个实现类来扩展就可以了。当然前提是我们的抽象要合理,要对需求的变更有前瞻性和预见性。抽象类不会有实例,一般作为父类被其他类继承,包含了子类的共同属性和方法。具体类是不被其他类所继承的,即子类继承了抽象类后,这个子类不应再被其他类所继承。

(7)迪米特法则

也称最少知识原则,一个对象应当对其他对象尽可能少地了解,让每个类专心做自己的事情而不去关心其他的事情,以降低耦合度。

(8)单一职责原则

不要存在多于一个导致类变更的原因,即一个类只负责一项职责。单一职责可以降低类的复杂度,其逻辑要比负责多项职责简单得多;提高类的可读性,提

相关文档
最新文档