基本要素
设计模式一般有以下四个基本要素
- 模式名称(Pattern Name):一个助记词,它用一两个单词来描述模式的问题、解决方案和效果。
- 问题(Problem):问题描述了应该在何时使用模式。
- 解决方案(Solution):解决方案描述了设计的组成部分、他们之间的相互关系及各自的职责和协作方式。
- 效果(Consequence):效果描述了模式应用的效果及使用模式应权衡的问题。
设计模式分类
创建型 | 结构型 | 行为型 | |
类 | Factory Method(工厂方法) | Adapter(适配器) | Interpreter(解释器) Template Method(模板方法) |
对象 | Abstract Factory(抽象工厂) Builder(生成器) Prototype(原型) Singleton(单例) | Adapter() Bridge(桥接) Composite(组合) Decorator(装饰) Facade(外观) Flyweight(享元) Proxy(代理) | Command(命令) Iterator(迭代器) Mediator(中介者) Memento(备忘录) Observer(观察者) State(状态) Strategy(策略) Visitor(访问者) |
各模式详解
创建型模式
概述
创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建、组合和表示它的那些对象。一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象。
随着系统演化的越来越依赖于对象复合而不是类继承,创建型模式变得更为重要。这种情况发生时,重心从一组固定行为的编码(Hard—coding)转移为定义一个较小的基本行为集,这些行为可以被组合成任意数目的更复杂的行为。这样创建有特定行为的对象要求的不仅仅是实例化一个类。
创建型模式比较
用于系统创建的那些对象的类对系统进行参数化有两种常用方法;生成创建对象的类的子类和对系统进行参数化的方法。前者应用于使用FactoryMethod方式,其主要缺点是仅为了改变产品类就可能需要创建一个新的子类。这种改变可能级联发生,例如如果产品的创建者本事是一个工厂方法创建的,那么也必须重定义它的创建者。后者更多的依赖于对象的复合,定义一个对象负责明确产品对象的类,并将它作为该系统的参数。这是AbstractFactory、Builder和Prototype模式的关键特征,都涉及创建一个新的负责创建产品对象的“工厂对象”。AbstractFactory由这个工厂对象产生多个对象。Builder由这个工厂对象使用一个相对复杂的协议,逐步创建一个复杂产品。Prototype由该工厂通过复制原型对象来创建产品对象。这种情况下,由于原型负责返回产品对象,所以工厂对象和原型是同一个对象。
结构型模式
概述
结构型设计模式涉及如何组合类和对象以获得更大的结构。结构型类模式采用继承机制来组合接口或实现。一个简单的例子是采用多重继承方法将两个以上的类组合成一个类,结果这个类包含了所有父类的性质。这一模式尤其有助于多个独立开发的类库协同工作。其中一个例子是类形式的Adapter模式,一般来说适配器使得一个接口与其他接口兼容,从而给出了多个不同接口的统一抽象。为此。类适配器对一个adaptee类进行私有继承。这样适配器就可以用adaptee(被适配者)的接口表示它的接口
结构型模式比较
Adapter(适配器)模式和Bridge(桥接)模式具有一些功能特性,都给另一个对象提供了一定程度上的间接性。因而有利于系统的灵活性,另外都涉及从自身以外的几个接口量这个对象转发请求。Adapter模式主要是为了解决两个已有接口之间不匹配的问题,不考虑这些接口是怎么实现的,也不考虑它们各自可能会如何演化。这种方式不需要对两个独立设计的类中的任何一个进行重新设计,就能够使它们协同工作。
Bridge模式则对抽象接口与它的(可能是多个)实现部分进行桥接。虽然这一模式运行使用者修噶实现它的类,但仍然为用户提供了一个稳定的接口,也会在系统演化时适应新的实现。Adapter模式和Bridge模式通常被用于软件生命周期的不同阶段,针对不同的问题。Adapter模式在类已经设计好后实施;而Bridge模式在设计类之前实施。
Composite(组合)模式和Decorator(装饰)模式具有类似的结构,说明它们都是基于递归组合来组织可变数目的对象。Decorator旨在能欧不需要生成子类即可给对象添加职责,这个避免了静态实现所有功能组合而导致子类极具增加。Composite旨在构造类,使多个相关的对象能够以统一的方式处理,而多重对象可以被当做一个对象来处理,重点在于表示。两者通常协同使用。
Decorator(装饰)模式和Proxy(代理)模式都描述了怎样为对象提供一定程度上的间接引用。Proxy模式构成一个对象并为用户提供一个一致的接口。与Decorator模式不同的是,Proxy模式不能动态的添加或分离属性,也不是为传递组合而设计的,它强调一种关系(Proxy与它的实体之间关系),这种关系可以静态的表达。其目的是,直接访问一个实体不方便或不符合需要时,为这个实体提供一个代替者,例如,实体在远程设备上,访问受限制或者实体是持久存储的。在Proxy模式中,实体定义了关键功能,而Proxy提供(或拒绝)对它的访问。在Decorator模式中,组件仅提供了部分功能,而一个或多个Decorator负责完成其他的功能。Decorator模式适用于编译时不能(至少不方便)确定对象的全部功能的情况。
行为型模式
概述
行为模式涉及算法和对象间职责的分配。行为模式不仅描述对象或类的模式,还描述它们之间的通信模式。这些模式刻画了在运行时难以跟踪的、复杂的控制流。它们将用户的注意力从控制流转移到对象间的联系方式上来。
行为型模式比较
很多行为模式注重封装变化。当一个程序的某个方面的特征经常发生变化时,这些模式就定义一个封装这个方面的对象。这样,该程序的其他部分依赖于这个方面时,它们都可以于此对象协作。这些模式通常定义一个抽象类来描述这些封装变化的对象,并且通常该模式依据这个对象来命名。例如:
- 一个Strategy对象封装一个算法
- 一个State对象封装一个与状态相关的行为。
- 一个Mediator对象封装对象间的协议。
- 一个Iterator对象封装访问和遍历一个聚集对中的各个组件的方法。
这些模式描述了程序中很可能会改变的方面。大多数模式有两种对象:封装该方面特性的新对象和使用这些新对象的已有对象。但并非所有对象行为模式都有这样的分割功能,录入Chain of Responsible(责任链)可以处理任意数目的对象(即一个链),而所有这些对象可能已经存在于系统中了。这也说明了行为模式的另一个不同点:并非所有的行为模式都定义类之间的静态通信关系。
一些模式引用总是被用作参数的对象。录入Visitor,一个Visitor对象是一个多态的Accept操作的参数,这个操作用于该Visitor对象访问的对象。其他模式定义一些可作为令牌进行传递的对象,这些对象将在稍后被调用。例如,Command和Memento。在Command中令牌代表一个请求;在Memento中,两台代表在一个对象在狗哥特定时刻的内部状态。在这两种情况下,灵台都可以有一个复杂的内部表示,但客户并不会意识到这一点。另外,在Command模式中多态特别重要,这是因为执行Command对象是一个多态操作。而Memnto接口非常小,以至于备忘录只能作为一个传递值,因此他可能根本不给它的客户提供任何多态操作。
Mediator(中介者)和Observer(观察者)是相互竞争的模式,它们之间的差别是:Observer通过引入Observer和Subject对象来分布通信,而Mediator对象则封装了其他对象间的通信。Observer模式中不存在封装一个约束的单个对象,而必须是Observer和Subject对象相互协作来维这个约束。通信模式由Observer和Subject连接的方式决定:一个Subject通常有多个Observer,并且有时一个Subject的Observer也是另一个Observer的目标。Observer模式有利于Observer和Subject之间的分割和松耦合,易于产生更细粒度且更易于复用的类。Mediator模式的目的是集中而不是分布,它将维护一个约束的职责直接放在了一个中间者中。
Command、Observer、Mediator和Chain of Responsibility等模式都涉及如何对发送者和接收者解耦。但各自有不同的权衡考虑。
Command模式使用一个Command对象来定义一个发送者和一个接收者之间的绑定关系,从而支持解耦。Command对象提供了一个提交请求的简单接口(即Execute操作),将发送者和接收者之间的连接定义在一个对象,使得该发送者可以与不同的接收者一起工作,达到将发送者和接收者解耦,使发送者更易于复用。此外可以服用Command对象,用不同的发送者参数化一个接收者。
Observer模式通用定义一个接口来通知目标中发生的改变,从而将发送者(目标)与接收者(观察者)解耦。Observer定义了一个比Command更松的发送者-接受者绑定,这是因为一个目标可能有多个观察者,并且其数目可以再运行时变化。此模式中的Subject和Observer接口是为了处理Subject的变化而设计的,因此,当对象间有数据依赖时,最好用此模式来对它进行解耦。
Mediator模式让对象通过一个Mediator对象间相互引用,从而对他们进行解耦。一个Mediator对象为各Colleague对象间的请求提供路由,并集中它们的通信。因此,各Colleague对象仅能通过Mediator接口互相通信。Mediator接口是固定的,为了增加灵活性,Mediator可能不得不实现他自己的分发策略。可以用一种方式对请求编码并打包参数,使得Colleague对象可以请求的操作数目不限。由于此模式将通信行为集中到一个类中而不是将其分布在各个子类中,所以他可以减少一个系统子类生成。
Chain of Responsibility模式通过演一个潜在接收者链传递请求而将发送者与接收者解耦。因为发送者和接收者之间的接口是固定的,责任链可能需要一个定制的分发策略。