您的位置:首页 > 其它

学习:设计模式 可复用面向对象软件的基础 【引言】

2012-01-07 00:51 537 查看
1.1什么是设计模式

问题一:什么是设计模式?

提供相关问题的解决方案

问题二:一个模式的基本要素是什么?

模式名称(pattern name)

问题(problem)

解决方案(solution)

效果(consequences)

1.2smalltalk MVC中的设计模式

类的模型/视图/控制器(Model/view/controller)

模型Model是应用对象,视图View是它在屏幕上的标示,控制器Controller定义用户界面对用户输入的响应方式。不使用MVC,用户界面设计往往将这些对象混在一起,而MVC则将他们分离以提高灵活性和复用性。

MVC通过建立一个“订购/通知”协议来分离视图和模型。视图必须保证它的显示正确地反映了模型的状态。一旦模型的数据发生变化,模型将通知有关的视图,每个视图相应地得到刷新自己的机会。这种方法可以让你为一个模型提供不同的多个视图表现形式,也能够为一个模型创建新的视图而无须重写模型。

MVC的主要关系是由Observer,Composite和Strategy三个设计模式给出的

Observer 反映了将视图和模型分离的设计,然而这个而设计还可用于解决更一般的问题:将对象分离,使得一个对象的改变能够影响另一些对象,而这个对象并不需要知道那些被影响的对象的细节。

Composite MVC的另一个特征是视图可以嵌套。例如,按钮控制面板可以用一个嵌套了按钮的复杂视图来实现。对象查看器的用户界面可由嵌套的视图构成,这些视图又可复用于调试器。MVC用View类的子类——CompositeView类来支持嵌套视图。CompositeView类的对象行为上类似于View类的对象,一个组合视图可用于任何视图可用的地方,但是它包含并管理嵌套视图。这个例子反映了可以将组合视图与其构件平等对待的设计,同样地,改设计也适用于更一般的问题:将一些对象划为一组,并将该组对象当作一个对象来使用。这个设计被描述为Composite模式,该模式允许你创建一个类层次结构,一些子类定义了原子对象(如Button)而其他类定义了组合对象(CompositeView),这些组合对象是由原子对象组合而成的更复杂的对象。

Strategy MVC允许你在不改变视图外观的情况下改变视图对用户输入的响应方式。例如:你可能希望改变视图对键盘的响应方式,或希望使用弹出式菜单而不是原来的命令键方式。MVC将响应机制封装在Controller对象中。存在着一个Controller的类层次结构,使得可以方便地对原有Controller做适当改变而创建新的Controller。View使用Controller子类的实例来实现一个特定的响应策略。要实现不同的响应策略只要用不同种类的Controller实例替换即可。甚至可以在运行时刻通过改变View的Controller来改变View对用户输入的响应方式。例如,一个View可以被禁止接收任何输入,只需要给它一个忽略输入事件的Controller。View-Controller关系是Strategy模式的一个例子。一个策略是一个表述算法的对象。当你想静态或动态替换一个算法,或你有很多不同的算法,或算法中包含你想封装的复杂数据结构,这时策略模式是非常有用的。

1.3描述设计模式

为了达到设计复用,我们必须同时记录设计产生的决定过程,选择过程和权衡过程。具体的例子也是很重要的,它们让你看到实际的设计。

设计模式的模板组成成分

模式名和分类

意图

(是回答下列问题的简单称述:设计模式是做什么的?它的基本原理和意图是什么?它解决的是什么样的特定设计问题?)

别名

动机

(用以说明一个设计问题以如何用模式中得类,对象来解决该问题的特定情景。该情景会帮助你理解随后对模式更抽象的描述。)

适用性

(什么情况下可以使用该设计模式?该模式可用来改进哪些不良设计?你怎样识别这些情况?)

结构

(采用基于对象建模技术的表示法对模式中的类进行图形描述。)

参与者

(指设计模式中的类和/或对象以及它们各自的职责。)

协作

(模式的参与者怎样协作以实现它们的职责。)

效果

(模式怎样支持它的目标?使用模式的效果和所需做的权衡取舍?系统结构的哪些方面可以独立改变?

实现

(实现模式时需要知道的一些提示,技术要点及应避免的缺陷,以及是否存在某些特定于实现语言的问题。

代码示例

已知应用

相关模式

(与这个模式紧密相关的模式有哪些?其间重要的不同之处是什么?这个模式应与哪些其他模式一起使用?)

1.4设计模式的编目

Abstract Factory:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类

Adapter:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

Bridge:将抽象部分与它的实现部分分离,使它们都可以独立地变化。

Builder:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

Chain of Responsibility:为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。

Command:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。

Composite:将对象组合成树形结构以表示“部分——整体”的层次结构。Composite使得客户对单个对象和复合对象的使用具有一致性。

Decorator:动态地给一个对象添加一些额外的职责。就扩展功能而言,Decorator模式比生成子类方式更为灵活。

Facade:为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

Factory Method:定义一个用于创建对象的接口,让子类决定将哪一个类实例化。Factory Method使一个类的实例化延迟到其子类。

Flyweight:运用共享技术有效地支持大量细粒度的对象。

Interpreter:给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中得句子。

Iterator:提供一种方法顺序访问一个集合对象中各个元素,而又不需暴露该对象的内部表示。

Mediator:用一个中介对象来封装一系列的对象交互。终结者使各对象不需要显式地相互引用,从而使耦合松散,而且可以独立地改变他们之间的交互。

Memento:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到保存的状态。

Observer:定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。

Prototype:用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。

Proxy:为其他对象提供一个代理以控制对这个对象的访问。

Singleton:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

State:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。

Strategy:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。

Template Method:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

Visitor:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用

于这些元素的新操作。

1.5组织编目

我们根据两条准则对模式进行分类。第一是目的准则,即模式是用来完成什么工作的。模式依据其目的可分为

创建型(Creational),结构型(Structural),或行为型(Behavioral)三种。创建型模式与对象的创建有

关;结构型模式处理类或对象的组合;行为型模式对类或对象怎样交互和怎样分配职责进行描述。

第二是范围准则,指定模式主要是用于类还是用于对象。类模式处理类和子类之间的关系,这些关系通过集成

建立,是静态的,在编译时刻便确定下来了。对象模式处理对象间的关系,这些关系在运行时刻是可以变化的

,更具动态性。从某种意义上来说,几乎所有模式都是用继承机制,所以“类模式”只指那些集中于处理类间

关系的模式,而大部分模式都属于对象模式的范畴。

创建型类模式将对象的部分创建工作延迟到子类,而创建型对象模式则将它延迟到另一个对象中。结构型类模

式使用继承机制来组合类,而结构型对象模式则描述了对象的组装方式。行为型类模式使用继承描述算法和控

制流,而行为型对象模式则描述一组对象怎样协作完成单个对象所无法完成的任务。

1.6 设计模式怎样解决设计问题

1.6.1 寻找合适的对象

客户请求是使对象执行操作的唯一方法,操作又是对象改变内部数据的唯一方法。由于

这些限制,对象的内部状态是被封装的,它不能被直接访问,它的表示对于对象外部是不可

见的。

面向对象设计最困难的部分是将系统分解成对象集合。因为要考虑许多因素:封装、粒

度、依赖关系、灵活性、性能、演化、复用等等,它们都影响着系统的分解,并且这些因素

通常还是互相冲突的。

设计模式帮你确定并不明显的抽象和描述这些抽象的对象。例如,描述过程或算法的对

象现实中并不存在,但它们却是设计的关键部分。S t r a t e g y ( 5 . 9 )模式描述了怎样实现可互换的

算法族。S t a t e ( 5 . 8 )模式将实体的每一个状态描述为一个对象。这些对象在分析阶段,甚至在

设计阶段的早期都并不存在,后来为使设计更灵活、复用性更好才将它们发掘出来。

1.6.2 决定对象的粒度

F a c a d e ( 4 . 5 )模式描述了怎样用对象表示完整的子系统,

F l y w e i g h t ( 4 . 6 )模式描述了如何支持大量的最小粒度的对象。其他一些设计模式描述了将一个

对象分解成许多小对象的特定方法。Abstract Factory(3.1)和B u i l d e r ( 3 . 2 )产生那些专门负责生

成其他对象的对象。Vi s i t o r ( 5 . 1 0 )和C o m m a n d ( 5 . 2 )生成的对象专门负责实现对其他对象或对象

组的请求。

1.6.3 指定对象接口

对象声明的每一个操作指定操作名、作为参数的对象和返回值,这就是所谓的操作的型

构( s i g n a t u r e )。对象操作所定义的所有操作型构的集合被称为该对象的接口( i n t e r f a c e )。对象

接口描述了该对象所能接受的全部请求的集合,任何匹配对象接口中型构的请求都可以发送

给该对象。

类型(type) 是用来标识特定接口的一个名字。如果一个对象接受“ Wi n d o w”接口所定义

的所有操作请求,那么我们就说该对象具有“ Wi n d o w”类型。一个对象可以有许多类型,并

且不同的对象可以共享同一个类型。对象接口的某部分可以用某个类型来刻画,而其他部分

则可用其他类型刻画。两个类型相同的对象只需要共享它们的部分接口。接口可以包含其他

接口作为子集。当一个类型的接口包含另一个类型的接口时,我们就说它是另一个类型的子

类型( s u b t y p e ),另一个类型称之为它的超类型( s u p e r t y p e )。我们常说子类型继承了它的超类型

的接口。

在面向对象系统中,接口是基本的组成部分。对象只有通过它们的接口才能与外部交流,

如果不通过对象的接口就无法知道对象的任何事情,也无法请求对象做任何事情。对象接口

与其功能实现是分离的,不同对象可以对请求做不同的实现,也就是说,两个有相同接口的

对象可以有完全不同的实现。

设计模式通过确定接口的主要组成成分及经接口发送的数据类型,来帮助你定义接口。

设计模式也许还会告诉你接口中不应包括哪些东西。

设计模式也指定了接口之间的关系。特别地,它们经常要求一些类具有相似的接口;或

它们对一些类的接口做了限制。

1.6.4 描述对象的实现

抽象类(abstract class)的主要目的是为它的子类定义公共接口。一个抽象类将把它的部分

或全部操作的实现延迟到子类中,因此,一个抽象类不能被实例化。在抽象类中定义却没有

实现的操作被称为抽象操作(abstract operation)。非抽象类称为具体类(concrete class)。

子类能够改进和重新定义它们父类的操作。更具体地说,类能够重定义( o v e r r i d e )父类定

义的操作,重定义使得子类能接管父类对请求的处理操作。类继承允许你只需简单的扩展其

他类就可以定义新类,从而可以很容易地定义具有相近功能的对象族。

1. 类继承与接口继承的比较

理解对象的类( c l a s s )与对象的类型( t y p e )之间的差别非常重要。


一个对象的类定义了对象是怎样实现的,同时也定义了对象的内部状态和操作的实现。

但是对象的类型只与它的接口有关,接口即对象能响应的请求的集合。一个对象可以有多个类型,不同类的对象可以有相同的类型。

当然,对象的类和类型是有紧密关系的。因为类定义了对象所能执行的操作,也定义了

对象的类型。当我们说一个对象是一个类的实例时,即指该对象支持类所定义的接口。

理解类继承和接口继承(或子类型化)之间的差别也十分重要。类继承根据一个对象的实现

定义了另一个对象的实现。简而言之,它是代码和表示的共享机制。然而,接口继承(或子类

型化)描述了一个对象什么时候能被用来替代另一个对象。

尽管大部分程序设计语言并不区分接口继承和实现继承的差别,但使用中人们还是分别

对待它们的。S m a l l t a l k程序员通常将子类当作子类型(尽管有一些熟知的例外情况[ C o o 9 2 ] ),

C + +程序员通过抽象类所定义的类型来操纵对象。

很多设计模式依赖于这种差别。例如, Chain of Responsibility(5.1)模式中的对象必须有一

个公共的类型,但一般情况下它们不具有公共的实现。在C o m p o s i t e ( 4 . 3 )模式中,构件定义了

一个公共的接口,但C o m p o s i t e通常定义一个公共的实现。C o m m a n d ( 5 . 2 )、O b s e r v e r ( 5 . 7 )、

S t a t e ( 5 . 8 )和S t r a t e g y ( 5 . 9 )通常纯粹作为接口的抽象类来实现。

2. 对接口编程,而不是对实现编程
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐