设计模式:
是面向对象的软件开发经验的总结,其中包含了软件设计中很多问题的解决方案和设计思路,是可直接利用的程序结构。
按照以下要点讨论设计模:
设计模式分类:
4.2构造型设计模式
(1)抽象工厂(Abstract Factory)模式
将系列产品的制造责任和部件封装起来,因为系列产品有着相同的构件部分,但每个系列产品的部件又有所不同。
应用可根据不同系列的产品需求,组织不同产品部件对象的创建,完成系列产品的制造。
利用多态性的动态绑定机制:
·用抽象类描述系列产品的制造部件;
·用继承来描述具体产品的实现;
·在应用中利用抽象类的各种操作设计系列产品的接口函数;
·在用应用中通过接口函数实现不同产品的统一建造过程。
AbstractFactory适用的软件问题:
(2)工厂方法(Factory Method)模式
对相同结构的不同应用实体,需要向不同的实体发送相应的操作请求,以完成各自不同的同一形式的操作。
在抽象类中利用的工厂方法由子类具体化,以得到结构相同的不同的对象实体。这样,可以向不同的实体发出消息,灵活地实现同类结构的不同实体的操作。
•在类的内部创建并得到对象,可以将类的某些职责委托给一个独立的类,用以扩充类的某种操作,达到平行扩展效果。
建立应用操作类与需要的对象实体类关联,用工厂方法创建并返回实际的对象实体,然后可以利用该实体对象完成必要的操作请求。
FactoryMethod适用的软件问题:
(3)转换器/生成器(Converter/Builder)模式
将不同对象的不同操作以同样的过程统一起来。
引导器通过关联Builder,完成统一的构造过程。 Builder子类中的各项操作,无论数量和内容都可能各不相同。
•在应用中定义所需要的引导器,用以完成统一步骤的处理,并用关联的构造器实例来完成相应的处理;
•根据需要从构造器继承子类来实现不同的处理方式。
Builder适用的软件问题:
对构造的三个模式的比较:
抽象工厂模式,定义一个创建系列产品的类,可根据需要定义相同系列的具体产品类,以适应需求的变化。
生成器模式,为解决系列产品的构造过程相同,但系列中的具体产品其部件成分可能不同。
工厂方法模式,针对产品的不可预定情况,用一个方法得到某个具体产品的实体,以完成不同产品的相同形式操作。
通常情况下,在Abstract Factory、Builder以及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)模式
用中介对象来封装同僚对象之间的交互行为,它使他们之间不需要显式地相互引用,构成松散耦合,可独立地改变它们之间的交互。
•将分布于多个对象间的行为形成统一的行为。
•各同僚对象实现解耦,可独立改变,并可复用Colleague和Mediator
•使多对多协议简化为一对多协议,关系易于理解和维护
•交互的复杂性集中于中介者。
(6)策略(Strategy)模式
把一系列同类的算法封装起来,使算法独立于应用,对同类算法的利用灵活可变。
•策略Strategy类提供了可重用的算法或行为。
•将算法或行为封装在Strategy类中,可以独立于Context改变它。
在三种类型的设计模式中,似乎有很多相似的模式。
了解模式之间的差异非常重要,因为它们针对的是面向对象设计过程中,一些特定的、经常发生的问题,给出了相应解决问题的方法和途径。
模式总是相互结合使用的,当在设计中需要权衡利弊、决定取舍时,了解多个模式,并能准确地区分它们,可以提供更大的设计空间和更多的选择余地。
• Adapter模式主要是为了解决两个已有接口之间的不匹配问题。它不去考虑接口是怎样实现的,也不考虑重新设计某个类,只是将已有类的对象不加修改地利用起来,协同工作。
• Bridge模式的主要目的是为提供稳定的接口。对接口与对应的实现部分进行桥接。对应的实现部分可能有多个,修改实现而不用改变接口。当然修改接口也不会影响实现。
这样,在选择采用模式时,当需要协同两个不兼容的类时,采用Adapter模式;当接口和实现可能会独立演变时,采用Bridge模式
Proxy模式的目的是,当直接访问一个实体不方便或不合需求时,为该实体提供一个替代者。
Proxy模式构成一个对象,并为应用提供一致的接口,但不能动态地添加或取消某种属性。
Proxy模式中,由实体定义关键的功能,而Proxy仅提供对实体的访问,它强调一种固定的关系,因此这种关系可以静态表达。
行为是程序中最有可能改变的因素。封状行为,为避免对象中的不定因素成为不可分割的部分,封装包括两种:
•封装某种行为特征的新对象
•封装某种行为特征的已有的对象
Strategy封装算法或行为
State封装状态相关的行为
Mediator封装对象之间的协议
Iterator封装访问和遍历的聚集对象
Observer与 Mediator模式的区别:
• Observer引入观察者和目标的相互协助来维持约束。一个目标可以有多个观察者,一个观察者也能够成为目标被观察。观察者和目标创建后立即被连接起来,需要知道它们之间的连接方式。观察者和目标是松散耦合。
• Mediator的目标是集中维护一个整体的约束。它使信息流简单,容易理解,不需要知道目标间的连接方式
合作的对象之间直接引用,会使它们相互依赖。这给系统的分层和重用带来困难。Observer、Mediator和Chain of Responsibility 模式,都涉及了将发送和接收解耦的问题。它们使用了不同的方式,有各自的权衡考虑。
• Observer观察者模式:通过定义一个接口来通知目标发生变化,使发送者和接收者解耦,它是为处理变化而考虑的。
• Mediator中介者模式:使对象通过中介对象间接相互引用,从而达到解耦。中介为各Colleague对象请求提供路由,采用分发策略。它是为不限定请求操作的数目而考虑的。
•责任链模式:通过沿着一个潜在的接收者链传递请求,这样,使发送者和接收者解耦。责任链也需要分发策略。它更多地考虑接收者和发送者的变化和扩充。