在之前的设计模式博客中,主要根据《Head First设计模式》谈了10个设计模式,今天来做下总结,好好梳理提炼x下精华,而且今天准备把GOF经典大作《设计模式》中的23个设计模式都总结一遍。(以下内容参考了程杰的《大话设计模式》)
在GOF的大作中,把23个设计模式做了分类:建造型,结构型,行为型。
建造型的设计模式有:抽象工厂,建造者,工厂方法,原型。
1.抽象工厂,它用于提供一个创建一系列或相关依赖对象的接口,而不需要明确指明类。
图中A、B代表不同的产品种类,1、2表示同种产品的不同分支,AbstractFactory是抽象工厂,它不关心实际生产出的具体产品,它只知道要生产一个包含A、B两种产品的一个系列产品,由它的子类,具体的工厂去决定生产的具体产品。
2. 建造者模式:将一个复杂对象的构建和表示分离,使得同样的建造过程可以创建不同的表示。
Build指明建造的过程,该过程会在Director被顺序执行。而在ConcreteBuilder中指明具体的表示(即实现了建造过程的方法),一般用于同类建造过程稳定的、内部表示容易改变的产品。该表表示只要定义一个新的ConcreteBuilder就可以了。
3.工厂方法:定义一个创建对象的接口,让子类决定实例化哪一个类。
工厂方法将具体产品的创建延迟到子类,实现了创建和使用的解耦。
4.原型模式:用原型实例指定创建对象的种类,并且通过这些原型创建新的对象。
5.单例模式:保证一个类只有一个实例,并提供一个访问它的全局访问点。
结构型有适配器,桥接,组合,装饰,外观,享元,代理。
6.适配器模式:将一个类的接口转化为客户希望的另一个接口,使得原来接口不兼容而不能一起工作的类可以一起工作。
适配器和期望的类实现同一接口,同时适配器持有被需要适配的类的引用,这样就可以完成类的接口适配器。
7.桥接模式:使抽象部分和实现部分分离,使它们可以独立的变化。
8.组合模式:将对象组合成树状结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
叶节点和枝节点实现共同的接口,但是实现方法的方法不同,枝节点可以持有枝节点或者叶节点的引用,而叶节点不能。客户端将叶节点和枝节点一视同仁,方便遍历,省去了冗长的判断语句。
9.装饰者模式:动态给对象添加一些额外的职责,比生成子类更加灵活。
Decorator持有ConcreteComponent的引用并为其添加职责,由于ConcreteComponent和Decorator实现同一个接口,所以被装饰者可以再一次被装饰。
10.外观模式:定义了一个高层的接口,为子系统的一组接口提供了一个一直一致的界面,使得子系统更加容易使用。
Facade类将原来各个类的一些方法封装成一个方法,按顺序调用,使得一次调用就可以完成原本需要多次调用的任务。
11.享元模式:运用共享技术有效的支持大粒度的对象。
当有大量类存在很多相似地方的时候可以用享元模式,可以大幅度减少实例化的类的对象,而对象间不同的部分,可以用其他对象来表示为外部状态。
12.代理模式:为其他对象提供代理以控制对这个对象的访问。
由于被代理类和代理类都实现了共同接口,所以只要是使用到被代理类的地方都可以用代理来代替。
行为型模式:观察者、模板方法、命令、状态、职责链、解释器中介者、访问者、策略、迭代器。
13.观察者模式:定义对象间一种一对多的依赖关系,当一个对象的状态发生变化时,所以依赖它的对象收到通知并自动更新。
只要实现了Observer接口的对象都可以被观察者观察,观察者不在意被观察的对象类型,所以实现了观察者和被观察者的解耦。每当观察者状态发生变化就自动调用被观察者的更新方法。
14.模板方法:定义一个算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重新定义该算法的某些步骤。
模板方法一般在TemplateMethod方法中定义了调用几个抽象方法PrimitiveOperation的调用顺序,而PrimitiveOperation的实现延迟到子类,这样可以根据子类的需要实现不同的执行行为,但是总的算法骨架没有改变。这样在节省重复代码的情况下确保了子类实现的灵活性。常用于创建各种框架。
15 命令模式:将一个请求封装成一个对象,从而使你可用不同的请求对客户进行参数化。也可以对请求进行排队或者记录请求日志以及支持撤销操作。
Receiver只在意接收到的对象是否实现了Command接口,命令类将请求封装在execute方法中,Receiver只要在需要的地方调用命令的execute方法即可,Receiver甚至不知道调用的命令是做什么的,实现了调用者和命令的解耦。
16 状态模式:允许一个对象在内部状态改变时改变它的行为,让对象看起来似乎修改了它的类。
一般将状态封装为独立的类,并将动作委托到当前状态对象,而Cotext状态的切换,是在状态类中完成的。实现了Cotext和状态类的解耦,让状态种类发生变化时系统修改起来很方便,可避免大量的判断语句。
17 职责链模式:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
各个处理对象通过SetSuccessor设置下一个处理对象,当自己无法处理时就将请求交给下一个对象,于是形成职责链,从而实现了请求和处理者的解耦,可避免大量的判断语句,也增加了职责链的灵活性(可动态修改)。
18 解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
19 中介者模式:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地互相引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
Mediator是各个Colleague的中介者,各个Colleague的交互都要通过中介者完成,实现了各个Colleague的解耦。
20 访问者模式:表示一个作用于某对象结构中的各个元素的操作。它使你可以在不改变个 元素的类的前提下定义作用于这些元素的新操作。
访问者模式将数据结构和作用于结构之上的操作之间的耦合解脱开,使得操作可以相对自由地演化,适用于数据结构比较稳定,又有易于变化的算法的情形。
21 策略模式:定义了一系列的算法,把它们一个个封装起来,并且使它们可以互相替换。本模式使得算法可以独立于它们的客户而变化。
策略模式实现了算法和算法实用类的解耦,算法之间也消除了耦合,使得算法的替换变得灵活方便。
22 备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样可以在以后将对象恢复到原先保存的状态。
Originator的状态被保存在了Memento中,Memento由Caretaker保管,不会影响到客户端。
23 迭代器模式:提供一种方法顺序访问聚合对象中各个元素,而不需要暴露该对象的内部表示。
迭代器Iterator将遍历一个聚合对象的算法封装起来。客户端只要得到一个实现Iterator接口的类对象的迭代器,就可以用统一的方式对聚合对象进行迭代操作。