每种设计模式的特点

设计模式:

是面向对象的软件开发经验的总结,其中包含了软件设计中很多问题的解决方案和设计思路,是可直接利用的程序结构。

按照以下要点讨论设计模:

l模式名称:表达设计思想的简单名字
l设计意图:针对的问题和解决问题的思路
l实现效果:达到的实际效果及作用
l技术途径:采用的技术方法和策略

设计模式分类:

构造式:涉及对象创建过程的模式
结构式:涉及对象类组合的模式
行为式:涉及对象之间交互操作的模式

4.2构造型设计模式

构造型设计模式,提供在系统中创建独立对象、创建组合对象,创建系列对象的基本方法。
构造型模式中,始终围绕的问题:
Ø将结构不同、功能不同的“产品”对象,用灵活的配置方式来创建,以适应未来的变化。
Ø怎样创建对象的问题,在何时创建?由谁来创建?

1)抽象工厂Abstract Factory模式

将系列产品的制造责任和部件封装起来,因为系列产品有着相同的构件部分,但每个系列产品的部件又有所不同。

应用可根据不同系列的产品需求,组织不同产品部件对象的创建,完成系列产品的制造。

利用多态性的动态绑定机制:

·用抽象类描述系列产品的制造部件;

·用继承来描述具体产品的实现;

·在应用中利用抽象类的各种操作设计系列产品的接口函数;

·在用应用中通过接口函数实现不同产品的统一建造过程。

AbstractFactory适用的软件问题:

希望系统可以由不确定的系列产品来配置,仅提供一个配置的框架
强调一系列相关对象的预先存在,以便进行组装和使用
使系统能适由于对象不同、组合不同,以及表示不同的多种情况
通常是与工厂方法配合使用的

2工厂方法Factory Method模式

对相同结构的不同应用实体,需要向不同的实体发送相应的操作请求,以完成各自不同的同一形式的操作。

在抽象类中利用的工厂方法由子类具体化,以得到结构相同的不同的对象实体。这样,可以向不同的实体发出消息,灵活地实现同类结构的不同实体的操作。

在类的内部创建并得到对象,可以将类的某些职责委托给一个独立的类,用以扩充类的某种操作,达到平行扩展效果。

建立应用操作类与需要的对象实体类关联,用工厂方法创建并返回实际的对象实体,然后可以利用该实体对象完成必要的操作请求。

FactoryMethod适用的软件问题:

当一个类不确定它所必须创建的对象的类时
希望由子类来指定所创建的对象时
当希望由子类来代理完成局部功能时,将创建对象的职责委托给某个子类。

3)转换器/生成器Converter/Builder模式

将不同对象的不同操作以同样的过程统一起来。

引导器通过关联Builder,完成统一的构造过程。 Builder子类中的各项操作,无论数量和内容都可能各不相同。

在应用中定义所需要的引导器,用以完成统一步骤的处理,并用关联的构造器实例来完成相应的处理;

根据需要从构造器继承子类来实现不同的处理方式。

Builder适用的软件问题:

当需要将对象的某些复杂处理过程或算法,与他的创建和组装方式相互独立时
当构造过程必须根据被构造的对象而有所不同时

对构造的三个模式的比较:

抽象工厂模式,定义一个创建系列产品的类,可根据需要定义相同系列的具体产品类,以适应需求的变化。

生成器模式,为解决系列产品的构造过程相同,但系列中的具体产品其部件成分可能不同。

工厂方法模式,针对产品的不可预定情况,用一个方法得到某个具体产品的实体,以完成不同产品的相同形式操作。

通常情况下,在Abstract FactoryBuilder以及Factory Method是相互结合使用的。

4.3构式设计模式

结构型设计模式,涉及如何组织对象类,成为适用的更大结构问题。

 结构型设计模式,主要针对希望灵活地实现新的功能的方法。

 结构型设计模式有很强的相似性,应该注意区分它们的设计意图,了解各自的优势和必须付出的代价。

1)适配器Adapter模式

为复用已有的成分,将不适应的接口转换成应用需要的另一个接口。

Adapter与原有的不同的Adaptee协同工作

使原来的目标请求方法适配成已有的对象方法。

Adapter模式是为解决两个已有接口之间的不匹配问题。

当需要不加修改地利用已有类的对象协同工作时,即协同两个不兼容的类时,可采用Adapter模式。

Adapter适用的软件问题:

需要使用一个已经存在的类,而它的接口不符合需求
需要创建一个可复用的类,该类可以与其它不相关或不可预见的类协同工作(不相关或不可预见表明接口不兼容)
需要使用一些已经存在的子类,但不可能对其一一匹配,可以适配它们的父类接口

2)桥(Bridge)模式

未来的需求,能应对操作接口和相关实现的操作独立演变。

分离与实现相关的部分,因为它们虽然有相同的操作,但却有不同的操作处理情况。用关联及多态机制建造稳定的接口,执行多种情况的不同实现。

将与实现环境相关操作部分独立

对外隐藏实现细节,实现应用透明访问

目的是为提供稳定的操作接口。将一般操作接口与实现环境相关的操作接口进行桥接,相关实现部分可能不同,替换实现而不用改变接口。当然修改操作接口也不会影响相关实现的操作部分。

Bridge适用的软件问题:

希望在抽象类和它的实现部分之间有一个固定的绑定关系
需要抽象类和它的实现部分分别加以扩充
希望实现部分的修改对外不产生影响。即客户代码不必重新编译
希望在客户不知道的情况下,多个对象间共享实现

3)代理(Proxy)模式

当直接访问某实体对象不合需求,又不希望对其直接修改,这样,可以为该实体提供一个替代者并采用相同的操作形式访问它,已完成某些必要操作,之后再由代理向主体转发实际的操作请求。

远程代理:可隐藏实际主体存在的不同地址空间

虚代理:可以实现优化处理,根据要求创建对象

保护代理:在访问实际主体时附加必要的处理。

  Proxy模式由实际主体定义关键的功能,而代理在完成必要的操作后,转发实际的访问请求,它强调这种固定的关系。

Proxy适用的软件问题:

需要用通用或复杂的对象的引用代替简单的引用,例如:远程代理、虚代理、保护代理、只能引导
对指针实际对象引用的计数
当第一次引用一个持久对象时,需要将其装入内存
在访问一个实际对象前,检查是否锁定了它,以确保其它对象不能改变它

4)装饰(Decorator)模式

将装饰器嵌入组件,用以完成对组件的必要的多项操作,这样可以回避使用多重继承解决方案带来的复杂性。

使用组件接口,为给定的对象类动态添加操作

通过装饰器的关联,使继承的每个操作责任类能够既执行自身的操作,又可转接执行给定对象类的操作。

Decorator适用的软件问题:

在不影响其它对象的情况下,以动态方式给对象添加职责
需要处理可以撤销的职责
当不能采用生成子类方式进行系统扩充时。

两种情况不能采用生成子类来扩充系统:

1)为支持大量独立扩充,而产生大量子类

2)类定义被隐藏或不能用于生成子类

4.4 行为式设计模式

行为型设计模式主要针对算法和对象之间的职责分配问题。
行为型设计模式不仅描述类或对象的结构模式,还要描述类或对象之间的通信模式。
对象之间的通信联系方式,反映了运行时难以跟踪的复杂的控制流。
行为型设计模式的基本策略是封装行为。

1)责任链(Chain Responsibility)模式

使请求和接收之间形成松散耦合关系。对象之间连成一条链,使对象沿着这条链传递请求,直到有一个对象处理它。这样,每个对象都有机会处理请求。

降低耦合。请求对象不用知道哪个对象处理请求,链中的对象也不用知道链的结构。

提高灵活性。可以方便简单地对链进行动态增加或改变处理责任。

代价是效率问题,以及并不保证请求一定能被接收处理。

ChainResponsibility适用的软件问题:

有多个对象处理一个请求,可在运行时自动确定由哪个对象来处理该请求
在不明确指定接收者的情况下,向多个对象中的某一个提交请求
可处理动态指定的一个请求的对象集合

2)观察者Observer模式结构

针对对象之间的一对多关系,当一个对象的状态发生变化时,所有依赖于它的对象都得到通知并被自动更新。这种模式起源于经典的MVC模式,也叫publish/subscribe发布/订阅模式。

当目标发生变化时,观察者与目标的状态产生不一致,目标需要通知各个观察者;

当观察者得到改变的通知后,向目标对象发出查询信息请求,用得到的查询信息使自己与目标对象状态保持一致。

可独立改变目标和观察者,可单独复用目标对象及观察者对象。

支持广播通信,目标发送通知不需要指定接收者,通知被自动广播给所有已向目标对象登记了的观察者,对于是否处理通知,完全取决与观察者,观察者的自由度很高。

如果观察者之间存在相关性,则存在意外的、不该更新的操作,必要时需要更复杂的约束条件和协议。

Observer适用的软件问题:

当一个抽象模型的两个方面,一个依赖于另一个时,将二者封装在独立对象中,以使它们可以各自独立改变和复用
当对一个对象的改变需要通知改变其它对象,而不知道具体有多少对象有待改变
当一个对象必须通知其它对象,而又不确定其他对象是谁,即不希望它们是紧密耦合的

3)状态模式

将与特定状态相关的行为局部化,将不同的行为分割开,每个特定状态所相关的行为被封装在一个独立的类中,这样,可以通过定义新的子类,来增加状态的方式转换。
使状态转换显式化,对不同的状态设立独立的对象,使状态转换明确。同时,由于状态转换操作的原子性,可保证状态的一致性。

将对象的状态作为一个对象类,封装状态类的行为,当对象的状态改变时,行为随之改变。

4)循环器Iterater模式

提供顺序访问聚合Aggregate对象(如:列表对象)的循环器超类,用继承方式封装不同聚合对象的不同遍历操作。每个聚合对象,都可以执行创建循环器的操作,并带着指向自身的指针作为操作的主体。

每个不同的具体循环器,支持以不同的方式遍历聚合的实体群。

循环器可简化聚合的操作接口,因为有了循环器的遍历操作接口,不再需要聚合操作接口了。

可以在同一个聚合上完成多种的遍历操作。

5)中介Mediator模式

用中介对象来封装同僚对象之间的交互行为,它使他们之间不需要显式地相互引用,构成松散耦合,可独立地改变它们之间的交互。

将分布于多个对象间的行为形成统一的行为。

各同僚对象实现解耦,可独立改变,并可复用ColleagueMediator

使多对多协议简化为一对多协议,关系易于理解和维护

交互的复杂性集中于中介者。

6)策略Strategy模式

把一系列同类的算法封装起来,使算法独立于应用,对同类算法的利用灵活可变。

策略Strategy类提供了可重用的算法或行为。

将算法或行为封装在Strategy类中,可以独立于Context改变它。

在三种类型的设计模式中,似乎有很多相似的模式。

了解模式之间的差异非常重要,因为它们针对的是面向对象设计过程中,一些特定的、经常发生的问题,给出了相应解决问题的方法和途径。

     模式总是相互结合使用的,当在设计中需要权衡利弊、决定取舍时,了解多个模式,并能准确地区分它们,可以提供更大的设计空间和更多的选择余地。

Adapter模式主要是为了解决两个已有接口之间的不匹配问题。它不去考虑接口是怎样实现的,也不考虑重新设计某个类,只是将已有类的对象不加修改地利用起来,协同工作。

Bridge模式的主要目的是为提供稳定的接口。对接口与对应的实现部分进行桥接。对应的实现部分可能有多个,修改实现而不用改变接口。当然修改接口也不会影响实现。

   这样,在选择采用模式时,当需要协同两个不兼容的类时,采用Adapter模式;当接口和实现可能会独立演变时,采用Bridge模式

Proxy模式的目的是,当直接访问一个实体不方便或不合需求时,为该实体提供一个替代者。

Proxy模式构成一个对象,并为应用提供一致的接口,但不能动态地添加或取消某种属性。

Proxy模式中,由实体定义关键的功能,而Proxy仅提供对实体的访问,它强调一种固定的关系,因此这种关系可以静态表达。

   行为是程序中最有可能改变的因素。封状行为,为避免对象中的不定因素成为不可分割的部分,封装包括两种:

   封装某种行为特征的新对象

   封装某种行为特征的已有的对象

Strategy封装算法或行为

State封装状态相关的行为

Mediator封装对象之间的协议

Iterator封装访问和遍历的聚集对象

ObserverMediator模式的区别:

Observer引入观察者和目标的相互协助来维持约束。一个目标可以有多个观察者,一个观察者也能够成为目标被观察。观察者和目标创建后立即被连接起来,需要知道它们之间的连接方式。观察者和目标是松散耦合。

Mediator的目标是集中维护一个整体的约束。它使信息流简单,容易理解,不需要知道目标间的连接方式

   合作的对象之间直接引用,会使它们相互依赖。这给系统的分层和重用带来困难。ObserverMediatorChain of Responsibility 模式,都涉及了将发送和接收解耦的问题。它们使用了不同的方式,有各自的权衡考虑。

Observer观察者模式:通过定义一个接口来通知目标发生变化,使发送者和接收者解耦,它是为处理变化而考虑的。

Mediator中介者模式:使对象通过中介对象间接相互引用,从而达到解耦。中介为各Colleague对象请求提供路由,采用分发策略。它是为不限定请求操作的数目而考虑的。

责任链模式:通过沿着一个潜在的接收者链传递请求,这样,使发送者和接收者解耦。责任链也需要分发策略。它更多地考虑接收者和发送者的变化和扩充。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章