Java设计模式之概述
一、定义
设计模式(Design Pattern)是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且提高代码的可靠性。设计模式是一种用于软件系统中不断重现的设计问题的解决方案进行文档化的技术,也是一种共享专家设计经验的技术。
GoF对设计模式的定义如下:
设计模式是在特定环境下为解决某一通用软件设计问题提供的一套定制的解决方案,该方案描述了对象和类之间的相互作用。
Design patterns are descriptions of communicating objects and classes that are customized to solve a
general design problem in a particular context.
基本要素
设计模式一般包含模式名称、问题、目的、解决方案、效果、实例代码和相关设计模式,其中的关键元素有以下4个:
- 模式名称(Pattern Name) ,在学习设计模式时首先应该准确记忆该模式的中英文名,在已有的类库中,很多使用了设计模式的类名通常包含了所使用的设计模式的名称,如果一个类的类名为XXXAdapter,则该类是一个适配器类,在设计时使用了适配器模式;如果一个类的类名为XXXFactory,则该类是一个工厂类,它一定包含了一个工厂方法用于返回一个类的实例对象;
- 问题(Problem),问题描述了应该在何时使用模式,它包含了设计中存在的我呢提以及问题存在的原因。这些问题有些是一些特定的设计问题,例如怎样使用对象封装状态或者使用对象表示算法等,也可能是系统中存在不灵活的类或对象结构,导致系统的可维护性较差。有时候,在模式的问题描述部分可能会包含使用该模式时必须满足的一系列先决条件。例如在使用桥接模式时系统中的类必须存在两个独立变化的维度,在使用组合模式时系统中必须存在整体和部分的层次结构等。在对问题进行描述的同时实际上就确定了模式所对应的使用环境以及模式的使用动机;
- 解决方案(Solution),解决方案描述了设计模式的组成部分,以及这些组成成分之间的相互关系、各自的职责和协作方式。模式是一个通用的模板,它们可以应用于各种不同的场合,解决方案并不描述一个特定而具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合(类或对象组合)来解决这个问题;
- 效果(Consequences),效果描述了模式应用的效果以及在使用模式时应权衡的问题。效果主要包含模式的优缺点分析,大家必须知道,没有一个解决方案是百分之百完美的,在使用设计模式时,需要进行合理的评价和选择。一个模式在某些方面具有优点的同时可能在另一方面存在缺陷,因此需要综合考虑模式的效果(如判断一个模式是否符合单一职责原则、是否符合开闭原则等);
分类
设计模式一般有两种分类方式:
1、根据目的分类
设计模式根据目的(模式是用来做什么的)可分为创建型(Creational)、结构型(Structural)和行为型(Behavioral)3类。
(1)创建型模式主要用于创建对象,GoF提供了5中创建型模式,分别是工厂方法模式(Factory Method)、抽象工厂模式(Abstract Factory)、建造者模式(Builder)、原型模式(Prototype)和单例模式(Singleton)。
(2)结构型模式主要用于处理类或对象的组合,GoF提供了7种结构型模式,分别是适配器模式(Adapter)、桥接模式(Bridge)、组合模式(Composite)、装饰模式(Decorator)、外观模式(Facade)、享元模式(Flyweight)和代理模式(Proxy)。
(3)行为型模式主要用于描述类或者对象怎样交互和怎样分配职责,GoF提供了11种行为型模式,分别是职责链模式(Chain of Responsibility)、命令模式(Command)、解释器模式(Interpreter)、迭代器模式(Iterator)、中介者模式(Mediator)、备忘录模式(Memento)、观察者模式(Observer)、状态模式(State)、策略模式(Strategy)、模板方法模式(Template Method)和访问者模式(Visitor)。
2、根据范围分类
设计模式根据范围(即模式主要用于处理类之间的关系还是处理对象之间的关系)可以分为类模式和对象模式两种。
(1)类模式处理类和子类之间的关系,这些关系通过继承建立,在编译时就被确定下来,是一种静态关系。
(2)对象模式处理对象间的关系,这些关系在运行时变化,更具动态性。
二、GoF设计模式简介
在GoF的经典著作《设计模式:可复用面向对象软件的基础》一书中一共描述了23种设计模式,这23种模式分别如表所示。
范围/目的 | 创建型模式 | 结构型模式 | 行为型模式 |
---|---|---|---|
类模式 | 工厂方法模式 | (类)适配器模式 | 解释器模式 模板方法模式 |
对象模式 | 抽象工厂模式 建造者模式 原型模式 单例模式 | (对象)适配器模式 桥接模式 组合模式 装饰模式 外观模式 享元模式 代理模式 | 职责链模式 命令模式 迭代器模式 中介者模式 备忘录模式 观察者模式 状态模式 策略模式 访问者模式 |
创建型模式(Creational Patterns)
- 抽象工厂模式(Abstract Factory Pattern)
- 提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
- 建造者模式(Builder Pattern)
- 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
- 工厂方法模式(Factory Method Pattern)
- 定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。
- 原型模式(Prototype Pattern)
- 使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。
- 单例模式(Singleton Pattern)
- 确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。
结构型模式(Structural Patterns)
- 适配器模式(Adapter Pattern)
- 将一个类的接口转换成客户希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作。
- 桥接模式(Bridge Pattern)
- 将抽象部分与它的实现部分解耦,使得两者都能独立变化。
- 组合模式(Composite Pattern)
- 组合多个对象形成树形结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。
- 装饰模式(Decorator Pattern)
- 动态地给一个对象增加一些额外的职责。就扩展功能而言,装饰模式提供了一种比使用子类更加灵活的替代方案。
- 外观模式(Facade Pattern)
- 为子系统种的一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
- 享元模式(Flyweight Pattern)
- 运用共享技术有效的支持大量细粒度对象的复用。
- 代理模式(Proxy Pattern)
- 给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。
行为型模式(Behavioral Patterns)
- 职责链模式(Chain of Responsibility Pattern)
- 避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求。将接收请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。
- 命令模式(Command Pattern)
- 将一个请求封装成一个对象,从而可用不同 的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。
- 解释器模式(Interpreter Pattern)
- 给定一个语言,定义它的方法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
- 迭代器模式(Interator Pattern)
- 提供一种方法顺序访问一个聚合对象中的各个元素,而又不用暴露该对象的内部表示。
- 中介者模式(Mediator Pattern)
- 定义一个对象来对象来封装一系列对象的交互。中介者模式使个对象之间不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
- 备忘录模式(Memento Pattern)
- 在不破坏封装的前提下捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。
- 观察者模式(Observer Pattern)
- 定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时其相关依赖对象皆得到通知并被自动更新。
- 状态模式(State Pattern)
- 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
- 策略模式(Strategy Pattern)
- 定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法可以独立于它的客户而变化。
- 模板方法模式(Tempate Method Pattern)
- 定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
- 访问者模式(Visitor Pattern)
- 表示一个作用于某对象结构中的各个元素的操作。访问者模式可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
需要注意的是,这23种设计模式并不是孤立存在的,很多模式之间存在联系,例如在访问者模式中操作对象结构中的元素时通常需要使用迭代器模式,在解释器模式中定义终结符表达式和非终结符表达式时可以使用组合模式;此外,还可以通过组合两个或者多个模式来设计同一个系统,在充分发挥每一个模式的优势的同时使它们可以协同工作,完成一些更复杂的设计工作。
三、优点
(1)设计模式融合了众多专家的经验,并以一种标准的形式供广大开发人员所用,它提供了一套通用的设计词汇和一种通用的语言以方便开发人员之间的沟通和交流,使得设计方案更加通俗易懂。对于使用不同编程语言的开发和设计人员可以通过设计模式来交流系统设计方案,每一个模式都对应一个标准的解决方案,设计模式可以降低开发人员理解系统的复杂度。
(2)设计模式使人们可以更简单、方便地复用成功的设计和体系结构,将已证实的技术表述成设计模式也会使新系统开发者更加容易 理解其设计思路。设计模式使得重用成功的设计更加容易,并避免那些导致不可重用的设计方案。
(3)设计模式使得设计方案更加灵活,且易于修改。在很多设计模式中广泛使用了开闭原则、依赖倒转原则、迪米特法则等面向对象设计原则,使得系统具有较好的可维护性,真正实现可维护性的复用。在软件开发中合理地使用设计模式可以使系统中的一些组成部分在其他系统中得以重用,而且在此基础上进行二次开发很方便。正因为设计模式具有该优点,所以在JDK、Struts、Spring、Hibernate、JUnit等类库和框架的设计中大量使用了设计模式。
(4)设计模式的使用将提高软件系统的开发效率和软件质量,并且在一定程度上节约设计成本。设计模式是一些通过多次实践得以证明的行之有效的解决方案,这些解决方案通常是针对某一类问题最佳的设计方案,因此可以帮助设计人员构造优秀的软件系统,并可直接重用这些设计经验,节省系统设计成本。
(5)设计模式有助于初学者更深入地理解面向对象思想,一方面可以帮助初学者更加方便地阅读和学习现有类库与其他系统中的源代码,另一方面还可以提高软件的设计水平和代码质量。
以上文字,大量摘抄自《Java设计模式》一书,由刘伟老师编著,故本文应当列入转载一类,有兴趣的朋友可以直接阅读原书。