前言
概念
设计模式(Design Pattern)是一套被反复使用、多数人知晓、经过分类编目的代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
“A pattern is a solution to a problem in a context”
设计模式是一种通用的解决问题的方法,它提供了在特定情境下解决一般问题的模板。
随着开发经验的积累,我们会逐渐形成一些常见的代码结构或解决问题的方法,这些就被称为"模式",我们可以在开发中重复利用这些模式。
1995 年,Eric Gamma、Richard Helm、Ralph Johnson、John Vlissides等人被称为“四人组”(Gang of Four,简称GoF),他们将开发者们这种经验总结整理成了一种称为“设计模式”的概念。并在 《设计模式:可复用面向对象软件的基础》 一书中详细介绍了23种常见的设计模式。
设计模式为开发人员提供了可以共享经验和理解的词汇,使得他们可以更容易地沟通和理解彼此的想法。
在本章节,我们将通过Java语言编写示例代码,逐一学习GoF的23种设计模式。通过学习设计模式,我们可以更加高效地解决问题,减少重复性的工作,提高代码的质量,开发出更易于复用和扩展的软件。
分类
创建型、结构型和行为型
根据模式的使用目的,可分为如下三种:
-
创建型模式(Creational Patterns):
- 通过提供实例化的机制来创建对象,以便在系统中某个地方只需指定其相关的类。
- 包括常见的模式如工厂模式、抽象工厂模式、单例模式等。
-
结构型模式(Structural Patterns):
- 关注如何组合类和对象以形成更大的结构。
- 例如,适配器模式、桥接模式、装饰器模式等。
-
行为型模式(Behavioral Patterns):
- 描述类和对象之间怎样相互协作和分配职责,以形成更大的系统。
- 包括观察者模式、策略模式、命令模式等。
类模式和对象模式
类模式和对象模式关注的是设计模式的应用范围。
-
类模式:
- 处理类与子类之间的关系,通常通过继承(或实现接口)建立。
- 这些关系在编译时刻就已经确定,具有静态性质。修改类模式可能需要重新编译整个程序。
-
对象模式:
- 处理对象之间的关系,这些关系在运行时刻可以动态变化。
- 更强调组合和委托,通常通过组合、聚合、或者其他方式来建立对象之间的关系。这使得系统更具有灵活性,能够在运行时动态改变对象的组合关系。
应用优势
设计模式的应用确实能够为软件开发带来许多优势:
-
更好地实现代码重用:
- 设计模式提供了一种经过验证的解决方案,可以在不同的情境中被重复使用,从而提高了代码的可重用性。
- 这有助于减少代码的重复编写,提高开发效率。
-
系统易于扩展(可维护性):
- 使用设计模式可以使系统更容易扩展。
- 当需要添加新的功能或修改现有功能时,通过设计模式的合理应用,可以降低对现有代码的影响,使系统更具有可维护性。
-
高可靠性:
- 设计模式有助于建立稳定、可靠的系统架构。
- 引入设计模式后,系统在增加新功能时,不容易引入错误或破坏原有的功能,提高了整个系统的稳定性和可靠性。
-
程序易于理解和交流:
- 使用设计模式可以提供一种标准化的解决方案,这使得程序的结构更加清晰和易于理解。
- 通过使用
UML
类图等工具,开发人员可以更轻松地交流和理解系统的设计。
创建型模式
创建型模式(Creational Pattern)对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离。
为了使软件的结构更加清晰,外界对于这些对象只需要知道它们共同的接口,而不清楚其具体的实现细节,使整个系统的设计更加符合单一职责原则。
创建型模式在创建什么(What),由谁创建(Who),何时创建(When)等方面都为软件设计者提供了尽可能大的灵活性。
创建型模式隐藏了类的实例的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的。
创建型模式(Creational Patterns)关注对象的创建过程,主要解决对象的实例化问题。通过提供更灵活、更直观的对象创建机制,创建型模式使得系统更加独立于类的实例化过程,从而使系统更加易于扩展和维护。
Factory Method Pattern
工厂方法模式(Factory Method)就是封装一个创建对象的抽象类(或者说接口),由该抽象类的子类来决定实例化哪一个产品类,因此我们说工厂方法模式将类的实例化延迟到子类中完成。产品类可以有很多个,作为客户端(调用者)来说,只需调用工厂方法获得产品即可(我要什么你就给我什么)。
Singleton Pattern
单例模式保证一个类只有一个实例,并提供一个全局访问点。
Prototype Pattern
原型模式通过复制现有对象来创建新对象,从而避免使用构造函数。
Abstract Factory Pattern
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类。
Builder Pattern
建造者模式将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
结构型模式
结构型模式(Structural Patterns)关注对象之间的组合,主要解决对象的组合问题。通过定义类和对象之间的关系,结构型模式使得系统更加灵活,更容易复用。
-
适配器模式(Adapter Pattern): 将一个类的接口转换成客户希望的另一个接口。
-
桥接模式(Bridge Pattern): 将抽象部分与它的实现部分分离,使它们可以独立地变化。
-
装饰者模式(Decorator Pattern): 动态地给对象添加额外的职责。
-
代理模式(Proxy Pattern): 为其他对象提供一种代理以控制对这个对象的访问。
-
外观模式(Facade Pattern): 为子系统中的一组接口提供一个一致的界面。
-
组合模式(Composite Pattern): 将对象组合成树形结构以表示“部分-整体”的层次结构。
-
享元模式(Flyweight Pattern): 通过共享技术来最小化内存或计算开销。
行为型模式
行为型模式(Behavioral Patterns)关注对象之间的通信,主要解决对象的协作问题。通过定义算法和对象之间的责任分配,行为型模式使得系统更加灵活,更容易维护。
-
模板方法模式(Template Method Pattern): 定义一个算法的骨架,将一些步骤延迟到子类中实现。这样,子类可以在不改变算法结构的情况下重新定义算法的某些步骤。
-
策略模式(Strategy Pattern): 定义一系列算法,将每个算法封装起来,并且使它们可以互相替换。客户端可以独立于算法的变化而使用不同的算法。
-
命令模式(Command Pattern): 将一个请求封装成一个对象,从而可以用不同的请求参数化客户端,并且能够支持请求的排队、记录和撤销操作。
-
职责链模式(Chain of Responsibility Pattern): 将请求的发送者和接收者解耦,使多个对象都有机会处理请求。将这些对象连接成一条链,并沿着这条链传递请求,直到有一个对象处理它。
-
状态模式(State Pattern): 允许一个对象在其内部状态改变时改变其行为,对象看起来好像修改了其类。
-
观察者模式(Observer Pattern): 定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
-
中介者模式(Mediator Pattern): 用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显式地相互引用,从而降低了它们之间的耦合。
-
迭代器模式(Iterator Pattern): 提供一种顺序访问一个聚合对象中各个元素的方法,而不暴露该对象的内部表示。
-
访问者模式(Visitor Pattern): 表示一个作用于某对象结构中的各元素的操作。它使你可以定义一个新的操作,而无需改变被操作的类。
-
备忘录模式(Memento Pattern): 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后将对象恢复到这个状态。
-
解释器模式(Interpreter Pattern): 提供了一个解释器,它定义了语言的语法规则的一种表示,并且使用该表示来解释语言中的句子。