23种设计模式详解

23种设计模式详解

设计模式是软件工程领域的重要基石,由Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四位作者在1994年出版的《设计模式:可复用面向对象软件的基础》中系统提出,因此被业界称为"GoF设计模式"。这23种模式历经三十年依然具有强大的生命力,是每位开发者必修的功课。本文按照"单工抽建原,适装桥组享代外,模备策观迭代责,访中解命状"的口诀顺序,逐一解析这些经典模式。

一、创建型模式:对象的诞生之道

创建型模式关注对象的实例化过程,将对象的创建与使用分离,提升系统的灵活性和可维护性。

单例模式(单) 确保一个类在整个应用程序生命周期内仅存在一个实例,并提供一个全局访问点。典型应用场景包括数据库连接池、线程池、配置管理器等需要共享资源的场景。实现方式包括饿汉式、懒汉式、双重检查锁定以及静态内部类等,其中枚举方式被认为是最佳实践,能够有效防御反射和序列化攻击。

工厂方法模式(工) 定义一个用于创建对象的接口,让子类决定实例化哪一个类。此模式将实例化操作延迟到子类,实现了开闭原则,使系统在不修改原有代码的情况下引入新产品。

抽象工厂模式(抽) 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。该模式适用于需要生成产品族的场景,例如跨平台UI组件库的构建,确保同一风格下的按钮、文本框、对话框等元素保持一致性。

建造者模式(建) 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。此模式特别适用于构造参数众多、存在多种配置组合的对象,如SQL查询构造器、HTTP请求构建等场景,通过链式调用提升代码可读性。

原型模式(原) 通过复制现有对象来创建新对象,避免了复杂的初始化过程。当对象创建成本较高或需要保存对象状态时,原型模式是理想选择,Java中的clone()机制是其典型实现。

二、结构型模式:对象的组合艺术

结构型模式关注如何组装类和对象以形成更大的结构,同时保持结构的灵活性和高效性。

适配器模式(适) 将一个类的接口转换成客户希望的另外一个接口,使原本因接口不兼容而不能一起工作的类可以协同运作。现实中的电源适配器正是此模式的生动隐喻,在集成第三方库或遗留系统时尤为常用。

装饰器模式(装) 动态地给一个对象添加一些额外的职责,相比生成子类更为灵活。Java I/O流体系是装饰器模式的典范应用,BufferedInputStreamFileInputStream的包装即为典型实例。

桥接模式(桥) 将抽象部分与它的实现部分分离,使它们都可以独立地变化。此模式有效应对多维度变化的场景,如不同形状与不同颜色的组合问题,避免了类爆炸式增长。

组合模式(组) 将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。文件系统的目录结构、UI组件的树形组织都是其经典应用。

享元模式(享) 运用共享技术有效地支持大量细粒度的对象,通过共享已存在的对象来减少内存占用。字符串常量池、围棋棋子的颜色共享均是此模式的实践体现。

代理模式(代) 为其他对象提供一种代理以控制对这个对象的访问。根据用途可分为远程代理、虚拟代理、保护代理和智能引用等类型,Spring AOP的动态代理机制是其现代应用的代表。

外观模式(外) 为子系统中的一组接口提供一个一致的界面,定义了一个高层接口使得子系统更加容易使用。此模式简化了客户端与子系统的交互,降低了系统间的耦合度。

三、行为型模式:对象的协作智慧

行为型模式关注对象之间的通信和职责分配,定义了对象间交互的算法和模式。

模板方法模式(模) 定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤,框架设计中的钩子方法即源于此思想。

备忘录模式(备) 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后恢复。编辑器的撤销功能、游戏存档机制均依赖此模式实现。

策略模式(策) 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。此模式让算法的变化独立于使用算法的客户,消除了冗长的条件分支语句。

观察者模式(观) 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。事件驱动架构、消息发布订阅系统均建立于此模式之上。

迭代器模式(迭) 提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。Java的Iterator接口、C#的IEnumerable都是此模式的标准化实现。

责任链模式(责) 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。审批流程、异常处理机制常采用此模式。

访问者模式(访) 表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。此模式适用于数据结构相对稳定但操作经常变化的场景。

中介者模式(中) 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。聊天室的服务器中介、MVC架构中的控制器都是其应用实例。

解释器模式(解) 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。正则表达式引擎、SQL解析器、简单的脚本语言解释器均基于此模式构建。

命令模式(命) 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。事务管理、任务调度、宏命令录制等功能均依赖此模式实现。

状态模式(状) 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。此模式将状态转换逻辑分布到状态类中,消除了庞大的条件语句,电梯运行状态、订单生命周期管理都是其典型应用场景。

结语

23种设计模式并非孤立存在的教条,而是经过实践检验的解决方案模板。深入理解这些模式的设计意图、适用场景及权衡取舍,能够帮助开发者在面对复杂系统时做出更优雅的设计决策,写出更具扩展性、可维护性的高质量代码。正如GoF所言:"程序应该是写来给人读的,只是顺便给机器执行而已。"设计模式正是通往这一目标的重要桥梁。

返回知识中心