设计模式概念
引用《设计模式-可复用的面相对像设计》对模式的定义是这样的:【Christopher Alexander 说过: “每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”, 尽管Alexander所指的是城市和建筑模式,但他的思想也同样适用于面向对象设计模式,只是在面向对象的解决方案里,我们用对象和接口代替了墙壁和门窗。两类模式的核心都在于提供了相关问题的解决方案。】
通俗的讲设计模式就是解决一类问题的解决方案,具有一定的普遍性,在碰到特定问题的时候使用特定的模式就能完美的解决,说白了设计模式就是解决特定问题的一系列套路。在面向对象软件设计中设计模式是解决特定设计问题的一系列方案或者说“套路”。这一系列解决方案是前辈们经过无数次的实践总结传承下来的宝贵经验,我们这些后来者可以直接学习前人的经验并应用到实际的工作中。一个模式应具有以下四个要素:
1. 模式名称(pattern name),它用几个简单的词语描述模式的问题,解决方案和效果。模式的名称有助于我们理解,记忆和交流,模式是建立在较高抽象层次的设计。通常模式名称更易于在实际项目中进行交流,模式名称可以增强设计词汇(设计语言)。如果不适用模式词汇我们在交流一个设计的时候会显得语言表达力不强,不够简洁甚至浪费时间,如果使用模式的词汇,交流时语言的表达力更强,有点像汉语中的成语,成语有更强的表达力。 举个例子:”我们要创建一个类来记录所有用户对这个模块的访问量,并且这个类在我们的正系统中有且只有一个实例“,说了这么多其实就是“单例模式”, 我们换成模式词汇表达就会更简洁更富有表达力“在这里我们使用【单例模式】”。
2.问题(problem) 描述了应该在何时使用模式。它解释了设计问题和问题存在的前因后果,它可能描述了特定的设计问题,如怎样用对象表示算法等。也可能描述了导致不灵活设计的类或对象结构。有时候,问题部分会包括使用模式必须满足的一系列先决条件。
3.解决方案(solution) 描述了设计的组成成分,它们之间的相互关系及各自的职责和协作方式。因为模式就像一个模板,可应用于多种不同场合,所以解决方案并不描述一个特定而具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合(类或对象组合)来解决这个问题。
4.效果(consequences) 描述了模式应用的效果及使用模式应权衡的问题。尽管我们描述设计决策时,并不总提到模式效果,但它们对于评价设计选择和理解使用模式的代价及好处具有重要意义。
设计模式分类
设计模式有两种分类方法:根据目的分(模式用来完成什么工作)和根据作用的范围来分(模式主要用于类上还是主要用于对象上)。
1.根据目的可分为:创建型 (Creational)、创建型 (Creational)、 和行为型(Behavioral)三种。创建型模式与对象的创建有关;结构型模式处理类或对象的组合;行为型模式对类或象怎样交互和怎样分配职责进行描述。
2.根据范围分为:类模式和对象模式。类模式处理类和子类之间的关系,这些关系通过继承建立,是静态的,在编译时刻便确定下来了。对象模式处理对象间的关系,这些关系在运行时刻是可以变化的,更具动态性。从某种意义上来说,几乎所有模式都使用继承机制,所以“类模式”只指那些集中于处理类间关系的模式,而大部分模式都属于对象模式的范畴。
设计模式分类:
目的 | ||||
创建型 (Creational) | 创建型 (Creational) | 行为型(Behavioral) | ||
范围 | 类 | 工厂模式(Factory Method Pattern) | 适配器模式(Adapter Pattern)【类】 | 解释器模式(In terpreter Pattern) |
简单工厂模式(Simple Factory Method Pattern) | 模板方法模式(Template Method Pattern) | |||
对象 | 抽象工厂模式(Abstract Factory Pattern) | 适配器模式(Adapter Pattern)【对象】 | 职责链模式(Chain of Responsibility Pattern) | |
建造者模式(Builder Pattern) | 桥接模式(Bridge Pattern) | 命令模式(Command Pattern) | ||
单例模式(Singleton Pattern) | 组合模式(Composite Pattern) | 迭代器模式(Iterator Pattern) | ||
原型模式(Prototype Pattern) | 装饰模式(Decorator Pattern) | 中介者模式(Mediator Pattern) | ||
外观模式(Facade Pattern) | 备忘录模式(Memento Pattern) | |||
享元模式(Flyweight Pattern) | 观察者模式(Observer Pattern) | |||
代理模式(Proxy Pattern) | 状态模式(State Pattern) | |||
策略模式(Strategy Pattern) | ||||
访问者模式(Visitor) |
设计模式不是孤立存在的他们之间存在着千丝万缕的联系。下面是GoF23个经典模式的关系:
GoF 23个经典设计模式的意图:
1.工厂模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。Factory Method使一个类的实例化延迟到其子类。
2.抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
3.建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
4.单例模式(Singleton Pattern):保证一个类仅有一个实例,并提供一个访问它的全局访问点。
5.原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。
6.适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另外一个接口。 Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
7.桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。
8.组合模式(Composite Pattern):将对象组合成树形结构以表示“部分 -整体”的层次结构。 Composite使得客户对单个对象和复合对象的使用具有一致性。
9.装饰模式(Decorator Pattern):动态地给一个对象添加一些额外的职责。就扩展功能而言, Decorator模式比生成子类方式更为灵活。
10.外观模式(Facade Pattern):为子系统中的一组接口提供一个一致的界面, Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
11.享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度的对象。
12.代理模式(Proxy Pattern):为其他对象提供一个代理以控制对这个对象的访问。
13.解释器模式(In terpreter Pattern):给定一个语言 , 定义它的文法的一种表示,并定义一个解释器 , 该解释器使用该表示来解释语言中的句子.
14.模板方法模式(Template Method Pattern):定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
15.职责链模式(Chain of Responsibility Pattern):为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。
16.命令模式(Command Pattern):将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。
17.迭代器模式(Iterator Pattern):给定一个语言 , 定义它的文法的一种表示,并定义一个解释器 , 该解释器使用该表示来解释语言中的句子。
18.中介者模式(Mediator Pattern):用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交。
19.备忘录模式(Memento Pattern):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到保存的状态。
20.观察者模式(Observer Pattern):定义对象间的一种一对多的依赖关系 ,以便当一个对象的状态发生改变时 ,所有依赖于它的对象都得到通知并自动刷新。
21.状态模式(State Pattern):用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。
22.策略模式(Strategy Pattern):定义一系列的算法 ,把它们一个个封装起来 , 并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。
23.访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
怎么选择设计模式
实际模式有很多光GoF的设计模式就一23中,那么我们在使用的过程中怎么去选择使用那种设计模式呢?
1. 根据设计模式的意图和目的去选择使用设计模式。
2.根据问题的类型去寻找与模式匹配的解决相似问题的设计模式。
3.考虑实际中的变化的部分。封装变化,那种模式更适合封装对应变化或者说能将变化的点控制在更小的范围内。
怎么使用设计模式
一旦你选择了一个设计模式该怎么使用呢?
1. 理解模式的意图和效果,确定选择的模式适合解决你的问题。
2.弄明白模式代码的组织结构。
3.弄明白模式参与者的角色。
4.创建模式中对应于你实际要解决问题的各个参与者和角色。
5.实现模式中对应角色的代码。
这乍看起来有些程式化,是的,这是针对初学这的一个引导思路。在实际使用中可不是这样的,如果这么生搬硬套的话,最后会发现很多设计模式不是被误用就是被滥用,变成了为了模式而模式,如果这样设计模式不但不能很好的解决设计问题反而成了将代码变得复杂难以理解难以维护的罪魁祸首。通常不要去模式优先而应该是业务优先遵守面向对象的设计原则,按照设计原则去组织,设计接口类以及其依赖关系,再通过重构自然就会得到模式。
学习设计模式更重要的是从前人的总结中汲取经验,学习设计模式要循序渐进,通过学习,模仿到灵活运用再到为自己的设计寻找灵感提高自身的设计能力。