Table of Contents generated with DocToc
书籍:《设计模式——可复用面向对象软件的基础》。
- 抽象工厂(Abstract Factory):通过抽象工厂创建对象,每个工厂可以创建一类多种具有关联的对象(这些对象具体类型都实现自一组接口类),不同具体工厂创建不同类别对象。
- 生成器(Builder):通过生成器对象来创建对象,以自行掌控对象各个部分的创建过程。
- 工厂方法(Factory Method):将创建对象的类型确定延迟到子类中。
- 原型(Prototype):通过克隆从未知具体类型(从统一接口派生)的已有对象上多态地创建相同类型对象。
- 单例(Singleton):整个环境中仅有单个(或有限数量个)对象,从一特定接口获取。
- 适配器(Adapter):将一个接口转换为另一个接口,以实现已有代码的兼容。
- 桥接(Bridge):同一接口可以有不同实现,依赖这个接口编程,在不同环境(比如操作系统)中使用不同实现,以屏蔽环境差异。
- 组合(Composite):为拓扑结构中不同具体类型的节点提供统一接口(常见于使用递归组合的树结构中)。
- 装饰器(Decorator):和现有对象实现同一接口,动态扩充已有组件功能。
- 外观(Facade):将系统中的子系统划分出来,提供统一外观(一组接口),降低系统中各个子系统间的耦合。
- 共享(Flyweight):通过一个对象池管理大量共享对象,通过引用共享对象避免创建大量重复对象。
- 代理(Proxy):为一个对象提供代理对象以控制对该对象的访问(例子:
vector<bool>
的operator[]
)。
比较:
- 适配器、桥接、外观:
- 适配器主要解决两个接口之间不匹配的问题,提供一个中间层实现兼容。使两个已有的不能配合的接口协同工作。在类(适配的那个接口)已经设计好后实施。
- 桥接则需要考虑多个系统的共性,实现各个系统共有的东西。在设计类(要实现的那个接口)之前实施。
- 外观模式相比适配器的区别是:外观模式提供一组新的接口,旨在解耦(高内聚低耦合),适配器利用已有接口,旨在让系统各部分能够协同工作。
- 组合、装饰器、代理:
- 组合旨在递归组合,对拓扑结构中的节点进行统一处理。
- 装饰器旨在不使用派生类即可给对象添加职责。
- 组合和装饰器目的不同,具有互补性,通常协同使用。
- 和装饰器一样,代理旨在为用户提供一致的接口。但与装饰器不同,代理不能动态添加或者分离性质,也不为递归组合而设计。
- 代理是在直接访问不方便时,对对象提供的一种间接访问方式。装饰器将自身实现为兼容源对象的接口,代理对象则是作为接口的一部分。
- 责任链(Chain of Responsibility):将请求沿着一个动态的接收者链条(通常实现为链表从前往后或者树结构中从下往上)传播,直到有接收者处理。(典型例子:GUI程序中消息的传播)。
- 命令(Command):将请求包装为对象,可用不同的请求对客户进行参数化,可以对请求进行排队、记录日志,以及支持事务、撤销等功能。
- 解释器(Interpreter):定义一个DSL,实现一个解释器以实现特定问题的高效、通用化处理。(例子:正则表达式处理字符串)。
- 迭代器(Iterator):提供一种不暴露聚合内部表示的顺序访问聚合各个元素的方法。
- 中介者(Mediator):通过一个中介对象来封装一系列对象之间的交互,使他们不需要显式相互引用,降低耦合,而且可以独立地改变他们之间的交互方式(通过实现新的中介对象)。(例子:Model-View-Controller模式中的Controller)。
- 备忘录(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便能够恢复到原先保存的状态。
- 维护备忘录具有一定代价,可以配合命令模式通过增量方式改变对象,还能实现撤销与重做。
- 观察者(Observer):定义对象间的一种一对多(并且松耦合——通过抽象层耦合)的依赖关系,当一个对象状态改变,通知所有依赖于它的对象进行更新。(GUI程序中常见,比如QT)
- 状态(State):允许一个对象在内部状态改变时改变它的行为,看起来像是修改了类一样。(可以用于实现状态机)
- 策略(Strategy):定义一系列算法,封装起来,使他们可以在运行时相互替换。使算法可以独立于客户而变化。
- 模板方法(Template Method):定义一个算法的骨架,将一些步骤延迟到子类中,使得在不改变算法结构的情况下重定义某些步骤。
- 访问者(Visitor):访问者表示一个作用于某对象结构内部个元素的操作,通过将访问者传入对象以实现访问操作。(可以将策略、解释器等对象作为访问者,访问者可以作用于递归组合起来的对象结构)
讨论:
- 封装变化:当程序某方面的特征可以变化时,这些模式把这种变化封装起来定义为一个可变的对象。这可以说是所有设计模式的核心思想之一,因为不再依赖变化部分的具体实现,封装变化天然能够降低耦合。
- 职责链将请求接收方封装为对象,并链在一起。
- 命令对象将一个可变的动作或者请求封装为对象。
- 解释器对象将一种DSL或一种DSL实现封装为对象。
- 迭代器对象封装访问和遍历聚集对象内各个元素的方法。
- 中介者对象封装对象间的协议。
- 备忘录模式将可能变化的对象内部状态封装为对象。
- 状态对象封装与状态相关的行为。
- 策略对象封装算法。
- 访问者对象将不同的访问操作封装为对象。
- 对象作为参数:一些模式引入总是作为参数的对象。
- 访问者模式将访问者作为参数。
- 命令模式和备忘录模式将对象作为参数到处传递。
- 封装通信行为还是分发每一次通信行为:
- 中介者对象将对象间的通信行为封装在内部。
- 观察者通过通知显式的发送接收行为来通信。
- 发送者接收者解耦:
- 当合作的对象间互相引用时,他们变得相互依赖,这对系统的分层和复用产生负面影响。
- 将请求包装为命令对象可以让发送方接收方松耦合。
- 观察者模式通过动态注册绑定发送者和接收者,将发送者与具体的接收者解耦,通过接口类耦合与接收方的具体实现解耦。
- 使用中介者对象作为发送方和接收方的中介可以使发送接收方松耦合。
- 职责链模式中将接收方串成一条链使得发送方和最终接收方解耦。