GoF的《设计模式》之入门介绍

转载请注明本文原始出处:GoF设计模式之入门介绍: http://java.learndiary.com/diaries/3150.jsp。本文在原始出处随时更新,欢迎批评指正和讨论。

--JAVA学习日记 littlebat 2007.04.02 16:33

正文:

*********************************************************************

用了一周多时间把这章看了一遍,并结合其中的内容把自己原来记的学习Thinking in Patterns with Java的日记复习了一下,感觉对各种设计模式的印象又清楚了一些,提起某个模式的名字大概知道了是怎么一回事。下面记下学习这章中的一些知识点和心得如下:

要做一个好的设计是困难的,设计模式的作用就是把这些被反复证明了的好的设计以一个统一的形式归纳记录下来。一旦一个设计的“套路“被证明是有效的,就像一个“浪漫小说“那样有一套固定的模式,可以反复的套来用。GoF总结的设计模式只是那些专家们知道的一个片断,还有像分布式编程、实时编程、设备驱动编程、面向特定应用领域编程等等的设计模式还有待别人去归纳整理(littlebat注:不知道这些领域的设计模式现在有没有?情况如何?学习领域现在不知有没有设计模式?也许学习日记可以在这方面看一看)。

1、什么是设计模式?

(The design patterns in this book are descriptions of communicating objects and classes that are customized to solve a general design problem in a particular context.)设计模式是在特定的环境中用来解决通用的设计问题的相互交流的对象和类。它的粒度不是细到讲怎么样实现一个链、一个哈希表,也不是粗到整个应用或者子系统。一个模式有4个基本元素:名称、解决的问题、解决的方案、结果。设计模式的实现的复杂程度跟选择的实现语言关系很大,所以有的设计模式在一种语言中实现起来很复杂,而在另一种语言中实现起来很简单,甚至有些模式已经被某种语言内置支持(littlebat注:像在Thinking in Patterns with Java中读到的那样,像Iterator, Observer, Adapter, Proxy等模式就在Java语言中内置支持,另外,Java中的clone()方法是否是prototype模式、Java的package是否是Facade模式、而Java的序列化技术是否是Memento的模式、Comparator是否是Strategy模式的内置支持还不是很清楚?)。这本书主要是采用C++(littlebat注:要复习一下c++语法了) 和 SmallTalk来实现例程。

2、Smalltalk MVC里的设计模式:

这一节分析了SmallTalk的MVC框架(littlebat注:Java中的Struts也是一种MVC实现)所涉及到的设计模式包括:Observer, Composite, Strategy, Factory method, Decorator等等。

3、描述设计模式:

这本书以一套固定的模版来描述一个设计模式,包括:名称和分类、目的、别名、动机(Motivation)、适用性、结构、参与的对象和类、参与者的交互、后果、实现、例程、已知的使用例子、相关模式。(littlebat注:其中为阐述结构,使用了现在UML的前身包含的一些技术,如OMT,交互图,序列图等等。。。我想,这些技术与UML应该差不多,有些区别通过看其它相关的内容也应该可以知道的。另外,UML好像是1997年才正式发布的?)

4、设计模式的目录:

这一节列出全部23种设计模式的目录和简短的描述,Abstract Factory (87), Adapter (139), Bridge (151),

Builder (97), Chain of Responsibility (223), Command (233), Composite (163), Decorator (175), Facade (185), Factory Method (107), Flyweight (195), Interpreter (243), Iterator (257), Mediator (273), Memento (283), Observer (293), Prototype (117), Proxy (207), Singleton (127), State (305), Strategy (315), Template Method (325), Visitor (331)。

组织目录:

GoF主要用两个标准来划分设计模式,一个标准是目的,分为:创建、结构、行为的目的。如下:

创建的目的:

Factory Method (107)

Abstract Factory (87)

Builder (97)

Prototype (117)

Singleton (127)

结构的目的:

Adapter (139)

Bridge (151)

Composite (163)

Decorator (175)

Facade (185)

Proxy (207)

行为的目的:

Interpreter (243)

Template Method (325)

Chain of Responsibility (223)

Command (233)

Iterator (257)

Mediator (273)

Memento (283)

Flyweight (195)

Observer (293)

State (305)

Strategy (315)

Visitor (331)

第二个分类的标准是模式使用的范围,包括:类的范围、对象的范围。如下:

类的范围:

Factory Method (107) Adapter (139) Interpreter (243)  Template Method (325)

对象的范围:

Abstract Factory (87)

Builder (97)

Prototype (117)

Singleton (127)

 Adapter (139)

Bridge (151)

Composite (163)

Decorator (175)

Facade (185)

Proxy (207)

 Chain of Responsibility (223)

Command (233)

Iterator (257)

Mediator (273)

Memento (283)

Flyweight (195)

Observer (293)

State (305)

Strategy (315)

Visitor (331)

书中还提出了也有其它的方式来组织设计模式,如有的设计模式经常放在一起用,有的可以互换,有的设计结果的结构相似等等。并特别的提出了一种根据设计模式间的关系来组织目录的方式,这就是很重要的设计模式的关系图(Figure 1.1,我把这张图放在了后面的附图中:图1.1)。

(littlebat注:我觉得关系图中的关系主要是一种模式使用了另一种模式的关系,如:图中的Composite模式使用了Iterator模式来遍历子对象,Iterator使用了Memento来保存遍历的状态。

另外,在Thinking in Patterns with Java中的分类是根据设计模式解决问题的性质,我本来以为在GoF的设计模式中没有按问题分类,结果是GoF把这种分类放在了设计模式怎样解决设计问题的下一节中。

另外,我发现了一些现在看来在这两本书中有点矛盾的地方:如在Bruce先生的书中说Decorater模式是解决类太多的问题(Thinking in Patterns chapter 9: too many),Bridge模式主要在用于代码的组织上(Thinking in Patterns chapter 10: Connecting different types),而在GoF的书上把这两种模式都归为在对象范围内应用的模式。也许他们是从不同的角度来说的,还需要进一步学习。

5、设计模式怎样解决设计问题

这一节是这一章中内容最多也算最重要的一节吧。它讲了oop设计者可能面临的各种设计问题和设计模式怎样帮助设计者解决这些设计问题。这些设计问题如下:

1)、找出恰当的对象

2)、决定对象粒度

3)、指定对象接口

4)、指定对象实现

   (1)类继承对接口继承

   (2)编程到接口而不是实现

5)、使重用技术运用起来

   (1)继承对组合

    要更多的使用组合

   (2)代理

   (3)继承对参数化类型

    取决于实现的系统

6)、关联运行时和编译时结构

7)、设计成适应改变的系统

   在这一节中指出了一些系统不易改变(灵活性差,稍有扩展和改变引发代价较大的重新设计)的问题和针对相应问题的设计模式:

    (1)精确的指定类来创建对象

       Design patterns: Abstract Factory (87), Factory Method (107), Prototype (117).

    (2)依赖特定的方法

       Design patterns: Chain of Responsibility (223), Command (233).

    (3)依赖硬件和软件平台

        Design patterns: Abstract Factory (87), Bridge (151).

    (4)依赖对象表现或实现

        Design patterns: Abstract Factory (87), Bridge (151), Memento (283), Proxy (207).

    (5)算法依赖

        Design patterns: Builder (97), Iterator (257), Strategy (315), Template Method (325), Visitor (331).

    (6)紧耦合

        Design patterns: Abstract Factory (87), Bridge (151), Chain of Responsibility (223), Command (233), Facade (185), Mediator (273), Observer (293).

    (7)用继承扩展功能

        Design patterns: Bridge (151), Chain of Responsibility (223), Composite (163), Decorator (175), Observer (293), Strategy (315).

    (8)不能方便的改变类

        Design patterns: Adapter (139), Decorator (175), Visitor (331).

   而对于这种改变灵活性的要求程度如何取决于所实现的系统,按灵活性要求从低到高分为3类系统:

    (1)应用程序

    (2)工具包

    (3)框架

     框架和模式的区别:

          1>、设计模式更抽象

          2>、设计模式是要小一些的结构元素

          3>、设计模式更通用化一些

这一节可以同Bruce先生从解决问题对设计模式进行的分类比较着看,Bruce先生根据设计模式解决的问题分成:

1>、Object quantity: Singleton

2>、Object decoupling: Proxy, State, Iterator

3>、Factoring commonality: Strategy, Policy, Template method

4>、Encapsulating creation: Factory method, Abstract factory

5>、Specialized creation: Prototype, Builder

6>、Too many: Flyweight(too many objects), Decorator(too many classes)

7>、Connecting different types: Adapter, Bridge

8>、Flexible structure: Composite

9>、System decoupling: Observer, Mediator

10>、Reducing interface complexity: Facade

11>、Algorithmic partitioning: Command, Chain of responsibility

12>、Externalizing object state: Memento

13>、Complex interactions: Visitor

14>、Multiple languages: Interpreter

现在看来,好像Bruce先生的针对解决问题的分类的可操作性要简单易懂一些。我印象比较深刻的就是那个Too many,例如:如果我在一个设计对应于现实对象的静态结构中找出了过多的类(像Bruce先生举的那个咖啡馆里的咖啡种类),我可以第一时间想到:这么多的类是不是用Decorator减少一些哟?当然,我还没有真正的实践过设计模式,也许真到那时使用这些设计模式也不是这么一回事。先记在这里回头再说吧。

另外,在这一节中有一些东西需要更进一步的学习,如class和type的区别,UML和OMT的区别?怎样用设计模式解决问题?还有,这一节的内容很多,不少东西都是粗粗读过,还需要在读完全书后再回过头来反复读,正如作者说,这不是一本看完一遍就扔在一边的书。

6、怎样选择一个设计模式

1)、想想设计模式怎样解决设计问题的

2)、查一下设计模式的意图

3)、研究一下设计模式的相互关系

4)、研究一下目的类似的设计模式

5)、检查一下引起重新设计的原因

6)、考虑一下你的设计中的变化因素

下面是书中的一个表,列出3种目的的设计模式可以解决的系统中的变化因素,描述格式是:设计模式      设计中可能变化的方面

1>,Creational

Abstract Factory (87) families of product objects

Builder (97) how a composite object gets created

Factory Method (107) subclass of object that is instantiated

Prototype (117) class of object that is instantiated

Singleton (127) the sole instance of a class

2>,Structural

Adapter (139) interface to an object

Bridge (151) implementation of an object

Composite (163) structure and composition of an object

Decorator (175) responsibilities of an object without subclassing

Facade (185) interface to a subsystem

Flyweight (195) storage costs of objects

Proxy (207) how an object is accessed; its location

3>,Behavioral

Chain of Responsibility (223) object that can fulfill a request

Command (233) when and how a request is fulfilled

Interpreter (243) grammar and interpretation of a language

Iterator (257) how an aggregate's elements are accessed, traversed

Mediator (273) how and which objects interact with each other

Memento (283) what private information is stored outside an object, and when

Observer (293) number of objects that depend on another object; how the dependent objects stay up to date

State (305) states of an object

Strategy (315) an algorithm

Template Method (325) steps of an algorithm

Visitor (331) operations that can be applied to object(s) without changing their class(es)

7)、怎样使用一个设计模式

讲当你选择了一个设计模式后怎样使用它。

    (1)把这个设计模式通读一遍

    (2)研究结构、参与者、交互部分

    (3)看例程部分

    (4)为设计模式中的参与者选定名字

    (5)定义类

    (6)为设计模式中的方法(操作)定义具体到应用的名字

    (7)实现模式中的方法

最后,这节讲了一个非常重要的观点,设计模式不能滥用,因为为达到灵活性等设计模式的使用常引入间接的附加的层次,这使系统变得复杂或(和)影响性能。只有设计模式提供的灵活性是系统真正需要的时候才使用它。后面的章节对评价一个设计模式的损益很有用。

*********************************************************************

附图:图1.1