Design Patterns学习:前言

来源:互联网 发布:大智慧for mac版 编辑:程序博客网 时间:2024/05/16 00:43

Design Patterns学习:前言

一、概述
A pattern is a proven solution to a recurring problem within a given context.

Design Patterns(设计模式,以下简称DP),源自Christopher Alexander的《建筑的永恒之道》,这个原本与软件设计不相关的概念经GoF(Gang of Four,指经典书籍《设计模式》的四位作者)引入软件设计领域,已有10余年,目前已发展成为OO领域的一个重要部分。近年来,在很多软件设计领域以外的其它领域,也尝试借用DP一词,但在本系列中,我们对这种情况不予考虑,但凡提及设计模式的地方,均指软件设计模式。

DP是对经过大量应用,并且行之有效的设计方法的抽象,在设计过程中合理地使用DP,可以使你的设计更好地适应变化,当改动不可避免时,合理运用DP的设计可以有效地减小改动的范围,同时,当对象间的关系趋于复杂时,合理运用DP的设计可以有效简化接口,从而使客户代码变得更加简单。
但是,DP同时也是OO中相对比较难以理解的部分,必须对OOD有了一定认识,才能理解DP的精髓。就我个人而言,早就对DP十分感兴趣,但苦于功力不够,一直觉得理解不够深刻,未敢把自己的理解写出来以示于人,但将自己对DP的感悟写出来的冲动促成了我的DP系列文章。然而,即便是今日,我斗胆将自己对DP的理解写下来,也绝非想证明自己是什么DP高人,只是想对自己所理解的DP写下来,以作为日后与大家作进一步讨论的基础。

由于DP的抽象,对于初学者而言,要读懂DP书籍并非易事,在研究DP时,参与讨论的往往是多个不同种类的类/对象/实例,这在一定程度上也增加了理解的难度,所以对于初学者而言,读DP的书需有一定的耐心,多一些思考,少一些浮躁。

二、模式分类
GoF的DP一书将设计模式分成3类23个模式来讨论,这也是几乎所有常见DP书籍进行分类和命名的方式:
Creational Patterns(用于动态创建对象)有5个,分别是:
Abstract Factory:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
Builder:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
Factory Method:定义一个用于创建对象的接口,让子类决定将哪一个类实例化。Factory Method使一个类的实例化延迟到其子类。
Prototype:用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。
Singleton:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

Structural Patterns(描述如何对一些对象进行组合,从而实现新功能的一些方法)有7个,分别是:
Adapter:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
Bridge:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
Composite:将对象组合成树形结构以表示“部分-整体”的层次结构,它使得客户对单个对象和复合对象的使用具有一致性。
Decorator:动态地给一个对象添加一些额外的职责。就扩展功能而言, 它比生成子类方式更为灵活。
Facade:为子系统中的一组接口提供一个一致的界面, Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
Flyweight:运用共享技术有效地支持大量细粒度的对象。
Proxy:为其他对象提供一个代理以控制对这个对象的访问。

Behavior Patterns(描述对象或类之间的通信模式)有11个,分别是:
Chain of Responsibility:为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。
Command:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。
Interpreter:给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。
Iterator:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
Mediator:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
Memento:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到保存的状态。
Observer:定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
State:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。
Strategy:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。
Template Method:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
Visitor:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

三、如何学习设计模式
GoF的DP一书读起来很累,以至于很多人第一次读的时候根本就不知所云(比如我,^_^),很多人认为之所以这本书这么难读是因为GoF的语言有失生动,模式划分或章节安排不合理。不可否认,GoF的DP一书对模式的划分存在少量的重合,此外,该书好像n年来没有勘误(尤其是中文版,部分印刷错误n年来都没有修正)和再版,但我认为,造成这本书难读的原因不在于该书本身,而在于读者。
学习设计模式需要有一些其它基础知识,在没有这些基础之前学习设计模式,肯定会有一定的难度,即便是已经有了这些基础知识,如果理解不深,学习设计模式仍然会有一定的难度。这些基础知识包括:
1、UML:UML是软件系统建模的标准语言,是软件设计者、开发者交流的基本工具,对于学习设计模式而言,由于类之间的关系是讨论的基础,只要读懂了每个模式对应的类图或其它图示,这个模式你就算学会一(小)半了。
2、必要的OOD知识:单纯懂UML,不可能使你完全明白每个类图所蕴藏的含义(所以,要读懂一半也不是那么容易的,^_^),要做到这一点需要对面向对象的一些指导性原则有一定了解,如开放-封闭原则(OCP)、Liskov替换原则(LSP)、依赖倒转原则(ISP)等(关于这些设计原则的详细介绍见参考2),限于篇幅,我不打算讨论OOD基本原则,但请记住以下的3D原则,它对于你理解所有设计模式都很有帮助:
Delegate, Divide and Delay.
即,尽可能的把职责委派出去,把结构细分,把具体实现推迟。
3、对于模式来说,除了“解决方案(solution)”(就是上面说的一<小>半)之外,最重要的元素还包括“问题(problem)”、“约束(force)”和“效果(consequence)”。每学习一个模式,除了要学习每个模式所代表的解决方案之外,还必须相应地学到该模式所适用的范围(由“问题”给出)、不适用的范围(由“约束”给出)和该模式造成的正反两面的效果。这就是模式的另一(大)半,因为每一种模式都是针对一定的问题的,没有一种模式是万能的,每个模式提出的目的在于通过合理的功能划分来实现High encapsulation, low Cohesion的目标,从而使得我们的应用能够更好地适应变化。GoF的DP一书正是从以上几个方面来介绍各Pattern的,而本系列以后的文章并没有严格从以上几个方面来讨论各设计模式,而是力图在基本描述的基础上,按照笔者对各模式特性的理解,尽可能多地将笔者的体会溶入其中,对于本系列所缺少的部分,请大家参考GoF的DP一书。

四、何时及如何使用设计模式
一般来说,设计模式是在重构过程当中反复出现的设计范例,到底一个系统应当使用什么样的设计模式,无法在项目刚一开始的时候就知道。
模式并不是一个可以套来套取的死东西,需要灵活运用。要理解设计模式背后的道理,然后运用这个道理,不要照抄设计模式。
同时应当注意,不要过度追求使用模式。要从自己的软件需求出发,找到最能体现需求的设计,并非使用了模式的设计就是好设计。
使用设计模式要注意首先要理解软件需求,然后需要理解OO理论和模式理论,最后要正确地讲设计模式应用待自己的系统中去。最后需要注意的是,使用什么设计模式,往往需要在对代码进行反复重构的过程当中才能知道。也就是说,没有人能够准确预测需要使用什么模式。
在设计的过程中,往往需要通过重构来改进设计,在重构的过程中引入设计模式进而实现减小耦合性、提高内聚性、提高可扩展性等设计目标。

五、推荐书目
以下是我推荐的DP学习用书(排名不分先后):
1.设计模式-可复用面向对象软件的基础 Erich Gamma等(GoF)
2.设计模式精解(Design Patterns Explained) Alan Shalloway等
3.Java Design Patterns: A Tutorial James W. Cooper
4.Thinking in Patterns with Java Bruce Eckel
以上几本书中,第一本无疑是所有DP书籍的鼻祖,现如今,所有讨论DP的书籍、文章几乎无一例外将其列在了参考数目当中。在本系列以后的文章中,我会多次提到上面的第一本书,并简称之为“GoF的DP一书”或“DP一书”。如果你读DP一书时遇到困难,建议你认真考虑自己出现问题的原因,因为对UML的不了解,对OOD思想的不了解,设计经验的不足等诸多方面都可能影响你的阅读,如果是某方面知识的缺失影响了你的阅读,那没有办法,你只能去补课,如果是设计经验的不足影响了你的阅读,建议你多参与讨论,很欢迎你在我的系列文章后面发表评论或参与讨论;同时热烈欢迎各方高手参与这里的讨论,修正本系列文章中的错误,对本系列文章中的遗漏进行补充,或提出各位在学习、应用中的深刻理解、经验或教训。

六、其它
需要说明的是,由于Pattern只是对经过大量应用,并且行之有效的设计方法的抽象,是对好的设计的归纳、总结,因此,GoF的DP一书所命名的23中模式并没有也不可能涵盖我们能够使用的所有的模式,还有很多其它的模式等待我们去发掘、提炼、研究。

由于涉及类与类之间的关系,类图是细化讨论的一个很好的选择,后续讨论假定读者已经熟知UML标记及基本的类关系、C++虚函数、多态(如果不了解虚函数、多态这些OO基本概念,大多数的设计模式都不可能准确理解,可以说,多态和面向接口编程是所有设计模式的基础)、Delegate(委托)等基本概念及基本的OOD知识,并能熟练运用STL。
整个讨论过程在谈及实现时以C++为主,兼顾Java,基本原则是涉及界面的示例采用Java编写,其它基本采用C++编写。所有类图采用本人发布的简易建模工具XModeler绘制,所有C++示例代码均在Visual Studio 2005 Express或VC6中编译测试通过,Java示例代码在JDK1.4下编译通过。

最后需要说明的是,我所给出的示例并非标准的不可修改的实现方法,只是为了作为文字说明和图例说明的补充,设计模式跟其它OOD的理念一样,是一种思想,一种(好)习惯,如何实现是次要的。

参考:
1、一枝看上去很美的花——书评《Java与模式》——BY熊节:http://www.dearbook.com.cn/Guide/ViewGuide.aspx?GuideID=291
2、设计模式的一般原则:http://alexv.blogchina.com/177495.html
3、微软中国社区技术聊天室:http://www.microsoft.com/china/community/chat/chatrecord/chat20030612.mspx
4、一句话Design Pattern:http://www.chinaxp.org/forum/viewThread.go?parentId=1051152504866&forum=2
5、A summary of OO Priciples: http://www.codeproject.com/gen/design/nfOORules.asp
6、Oo Design Principles: http://c2.com/cgi/wiki?OoDesignPrinciples

 
原创粉丝点击