首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >经典设计模式概述

经典设计模式概述

原创
作者头像
大飞felix
发布2026-01-07 19:10:51
发布2026-01-07 19:10:51
2190
举报

一. 创建型模式(Creational Patterns)——5种

这类模式提供创建对象的机制,能够提升已有代码的灵活性和可复用性。

包括:工厂方法模式、抽象工厂模式、建造者模式、原型模式、单例模式。

1.工厂方法模式

定义一个用于创建对象的接口(工厂方法),但由子类决定要实例化的具体类。工厂方法让类的实例化延迟到子类。

  • 不直接在代码中 new 一个具体对象,而是通过调用工厂方法来创建对象。
  • 工厂方法定义在父类(通常是抽象类或接口)中,但具体的创建逻辑由各个子类去实现。
  • 这样可以将对象的创建与使用分离,增强代码的扩展性和维护性。

2.抽象工厂模式

提供一个接口,用于创建相关或依赖对象的家族,而不需要指定它们具体的类

  • 不是只创建一个单一对象,而是提供一个工厂接口,该接口可以创建一组具有共同主题或属于同一产品族的多个相关对象
  • 具体的产品族由具体工厂实现,客户端代码面向抽象工厂和抽象产品编程,不依赖具体实现类。
  • 这样可以确保创建出来的对象是相互兼容的,同时让系统更容易切换不同的产品族,增强了扩展性和灵活性。

3.建造者模式

将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。

  • 不直接通过一个复杂的构造函数或单一方法来创建对象,而是将对象的构造过程拆分为多个步骤,由一个专门的“建造者”类来负责逐步构建对象的不同部分。
  • 最终通过一个指挥者(Director,可选)或直接调用建造者方法,来得到一个完整、配置灵活的对象。

4.原型模式

通过复制(克隆)现有对象来创建新对象,而不是通过新建类实例的方式。

当创建一个对象的成本较高(比如需要进行大量初始化或计算),或者希望动态地生成对象时,可以事先创建一个“原型”对象,然后通过克隆(clone)这个原型来快速生成新的对象,而无需每次都调用构造函数。

5.单例模式

保证一个类在整个程序运行期间只有一个实例,并提供一个全局访问点来获取这个实例。

无论何时何地调用,该类都只会创建唯一的一个对象,避免重复创建实例,节省资源,同时便于统一管理和控制。

常见实现方式:

  • 懒汉式(使用时才创建,需处理线程安全)
  • 饿汉式(类加载时就创建,线程安全但可能浪费资源)
  • 双重检查锁定(DCL,兼顾效率与安全)
  • 静态内部类(推荐,线程安全且懒加载)
  • 枚举(最简洁安全的实现方式,推荐使用)

二. 结构型模式(Structural Patterns)——7种

这类模式介绍如何将对象和类组装成较大的结构,并同时保持结构的灵活和高效。

包括:适配器模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式、代理模式。

1.适配器模式

将一个类的接口转换成客户期望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。

  • 接口转换:通过中间适配器类,将不兼容的接口(如第三方库、旧系统接口)转换为客户端期望的接口。
  • 兼容性桥梁:让原本因接口差异无法直接协作的类(如新系统调用旧组件、不同标准接口对接)能够无缝合作。
  • 复用现有功能:无需修改原有类代码,通过适配器复用其功能,同时满足新需求。

关键组成

  • Target(目标接口):客户端期望使用的接口(通常是统一的标准或新系统的规范)。
  • Adaptee(被适配者):需要被适配的现有类(接口与目标不兼容,但包含可用功能)。
  • Adapter(适配器):实现目标接口,内部持有被适配者对象,将目标接口的方法调用转换为对被适配者方法的调用。

类型

  • 类适配器(通过继承实现):适配器继承被适配者类,同时实现目标接口(Java等单继承语言受限)。
  • 对象适配器(通过组合实现):适配器持有被适配者对象的引用(更灵活,推荐使用)。

典型特征

  • 透明转换:客户端仅感知目标接口,无需了解被适配者的存在。
  • 灵活扩展:新增适配器即可支持新的被适配者,无需修改客户端代码。
  • 解耦:隔离客户端与被适配者的直接依赖,降低耦合度。

适用场景

  • 集成第三方库/旧系统:第三方组件的接口与当前系统不兼容(如不同数据库驱动、遗留代码接口)。
  • 统一多来源接口:多个类提供相似功能但接口不同(如不同支付平台的API统一成标准支付接口)。
  • 复用不兼容的类:已有类功能符合需求,但接口与当前系统设计冲突(如旧版SDK适配新版框架)。

2.桥接模式

将抽象部分与实现部分分离,使它们可以独立变化。通过组合而不是继承来连接抽象与实现。

  • 解耦抽象与实现:将抽象(业务逻辑/功能定义)和实现(底层具体实现/平台)拆分成两个独立的层次,通过组合关系连接,而不是继承。
  • 独立变化:抽象和实现可以各自独立扩展(如新增抽象功能或更换实现方式),互不影响。
  • 避免类爆炸:替代多层继承导致的复杂类结构(例如不同颜色+不同形状的组合,用桥接模式比继承更简洁)。

关键组成

  • Abstraction(抽象类):定义高层控制逻辑,包含一个对实现接口(Implementor)的引用(组合关系),调用实现类的方法完成具体功能。
  • RefinedAbstraction(扩展抽象类):继承或扩展Abstraction,细化或增加新的抽象功能(如不同形状的绘制逻辑)。
  • Implementor(实现接口):定义底层具体实现的接口(如绘图API、硬件驱动等),不关心抽象层的业务逻辑。
  • ConcreteImplementor(具体实现类):实现Implementor接口,提供底层的具体实现(如OpenGL绘图、VGA显示驱动等)。

典型特征

  • 组合优于继承:通过对象组合(抽象持有实现接口的引用)实现松耦合,替代多层继承的刚性结构。
  • 双重扩展性:抽象层和实现层可独立扩展新功能,新增抽象或实现均无需修改对方代码(符合开闭原则)。
  • 动态绑定:运行时可以灵活切换实现(如更换不同的底层驱动或平台)。

适用场景

  • 需要分离抽象与底层实现,并让它们独立变化(如跨平台UI组件:抽象是按钮/文本框,实现是Windows/macOS/Linux的绘图API)。
  • 避免多层继承导致的类爆炸(例如不同颜色+不同形状的组合,用桥接模式比继承更易维护)。
  • 系统需要在多个维度上扩展(如消息通知:抽象是通知类型(邮件/短信),实现是发送渠道(云服务))。

3.组合模式

将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

  • 树形结构建模:用统一的接口处理简单元素(叶子节点)和复杂容器(分支节点),形成递归的树状结构。
  • 一致操作:客户端无需区分处理的是单个对象还是组合对象,对它们的操作方式完全相同。
  • 递归组合:分支节点(组合对象)可以包含其他分支节点或叶子节点,形成任意复杂的嵌套结构。

关键组成

  • Component(抽象组件):定义所有对象的通用接口(包括叶子节点和组合节点),声明共同操作(如显示、添加/删除子节点等)。
  • Leaf(叶子节点):表示树形结构中的叶子对象(无子节点),实现抽象组件的基本操作。
  • Composite(组合节点):表示包含子节点的分支对象,内部维护子组件集合(可以是叶子或其他组合节点),实现抽象组件的操作并递归调用子节点的方法。

典型特征

  • 统一处理:客户端代码可以一致地对待单个对象和组合对象(例如统一调用display()方法)。
  • 递归组合:组合节点可以无限嵌套,形成任意复杂的层级结构(如文件系统、组织架构)。
  • 灵活性:可动态添加或删除子节点,支持运行时修改树形结构。

适用场景

  • 需要表示对象的“部分-整体”层次结构(如文件系统:文件和文件夹、组织架构:员工和部门)。
  • 希望客户端忽略组合对象与单个对象的区别(例如统一遍历树形结构的节点)。
  • 动态构建复杂的树形结构(如GUI中的容器控件嵌套:窗口包含面板,面板包含按钮和文本框)。

4.装饰器模式

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。

  • 动态扩展功能:在不修改原有对象代码的前提下,通过包装(装饰)的方式为其添加新功能。
  • 灵活组合:可以嵌套多个装饰器,按需组合出不同的功能增强效果。
  • 替代继承:通过对象组合而非继承来扩展功能,避免子类膨胀问题。

关键组成

  • Component(抽象组件):定义被装饰对象和装饰器的共同接口(如原始功能的方法)。
  • ConcreteComponent(具体组件):实现抽象组件的核心功能(被装饰的原始对象)。
  • Decorator(抽象装饰器):继承/实现抽象组件,并持有一个组件对象的引用(组合关系),是装饰器的基类。
  • ConcreteDecorator(具体装饰器):继承抽象装饰器,实现具体的附加功能,并在调用原始功能前后添加新行为。

典型特征

  • 透明性:装饰后的对象与原对象接口一致,客户端无需感知是否被装饰。
  • 动态嵌套:多个装饰器可以层层包裹,形成链式调用(如先加密再压缩的数据流)。
  • 职责分离:每个装饰器只关注一个特定功能的增强,符合单一职责原则。

适用场景

  • 需要动态、透明地扩展对象功能(如运行时为对象添加日志、缓存、权限校验等)。
  • 避免子类爆炸:当通过继承扩展功能会导致大量子类时(例如不同功能组合的文本处理类)。
  • 功能组合灵活:需要按需组合多种增强行为(如IO流中的缓冲、加密、压缩等装饰)。

5.外观模式

为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

  • 简化复杂系统:将一个复杂子系统(多个类/模块的交互)封装成一个简单的高层接口(外观类),客户端只需与外观类交互,无需直接操作子系统内部细节。
  • 统一入口:为子系统提供统一的访问点,隐藏内部多个类之间的复杂调用关系和依赖。
  • 解耦客户端与子系统:降低客户端与子系统的耦合度,子系统内部变化时(如类结构调整),只要外观接口不变,客户端代码不受影响。

关键组成

  • 子系统类(多个):实现具体业务功能的类集合,这些类可能存在复杂的交互逻辑(例如数据库操作类、网络请求类、工具类等)。
  • 外观类(Facade):提供一个高层接口,内部聚合(组合或依赖)子系统中的多个类,封装了子系统的复杂调用流程,对外提供简单、统一的操作方法。
  • 客户端(Client):仅需与外观类交互,通过调用外观类的简单方法来间接使用子系统的功能,无需了解子系统内部的具体实现和类之间的协作关系。

典型特征

  • 简化调用:客户端通过一个简单的接口就能完成原本需要复杂步骤才能实现的功能,降低了使用成本。
  • 封装复杂性:将子系统内部的复杂逻辑和类之间的依赖关系封装在外观类内部,对外呈现简洁的调用方式。
  • 松耦合:客户端与子系统之间通过外观类进行交互,减少了直接的依赖关系,提高了系统的可维护性和可扩展性。

适用场景

  • 需要简化复杂子系统的使用:当一个子系统由多个类组成,且这些类之间的交互关系复杂,客户端直接使用难度较大时(例如电商系统中的订单处理、库存管理、支付等多个模块的协同)。
  • 为多个客户端提供统一入口:不同的客户端(如前端页面、移动端应用、第三方服务等)需要调用同一子系统的功能,通过外观类提供统一的接口,方便管理和维护。
  • 分层架构中的中间层:在系统分层设计中,外观类可以作为高层业务逻辑层与底层子系统层之间的中间层,隔离两者的直接依赖,提高系统的灵活性和可扩展性。

6.享元模式

运用共享技术有效地支持大量细粒度的对象。

  • 对象共享:将对象分为「内部状态」(可共享的不变部分)和「外部状态」(不可共享的可变部分),通过共享内部状态来减少对象数量。
  • 分离变与不变:将对象的不变部分(内部状态)提取出来共享,可变部分(外部状态)由客户端在使用时传入。
  • 节省资源:通过共享大量相似对象,避免重复创建,显著减少内存占用和提高性能(尤其适用于对象数量多但差异小的场景)。

关键组成

  • Flyweight(抽象享元类):定义享元对象的接口,通常包含操作外部状态的方法(如渲染、显示等)。
  • ConcreteFlyweight(具体享元类):实现抽象享元类,存储内部状态(可共享的部分),并提供操作外部状态的功能。
  • FlyweightFactory(享元工厂类):负责创建和管理享元对象,维护一个享元池(如Map),确保相同内部状态的对象只被创建一次,后续直接复用。
  • Client(客户端):维护外部状态(不可共享的部分),并向享元工厂请求享元对象,传入外部状态以完成具体操作。

典型特征

  • 共享机制:通过工厂类维护享元池,确保相同内部状态的对象全局唯一,重复使用时直接从池中获取。
  • 状态分离:内部状态(如字符的字体、颜色模板)被共享,外部状态(如字符的位置、大小)由客户端动态传入。
  • 性能优化:大幅减少重复对象的创建,降低内存消耗和GC压力(典型应用于大量相似对象的场景)。

适用场景

  • 系统存在大量相似对象:如文本编辑器中的字符对象(字体/样式相同但位置不同)、游戏中的树木/子弹对象(模型相同但坐标不同)。
  • 对象的大部分状态可外部化:将可变部分(外部状态)从对象中剥离,仅共享不变部分(内部状态)。
  • 需要显著减少内存占用:通过共享技术优化资源使用(如数据库连接池、线程池的本质也是享元思想的变体)。

7.代理模式

为其他对象提供一种代理以控制对这个对象的访问。

  • 间接访问:通过一个代理对象(与目标对象实现相同接口)控制对真实目标对象的访问,客户端不直接操作目标对象,而是通过代理间接调用。
  • 增强功能:代理对象可以在调用目标对象前后添加额外逻辑(如权限校验、日志记录、缓存等),而无需修改目标对象本身。
  • 职责分离:将访问控制、增强逻辑与核心业务分离,目标对象专注于自身功能实现。

关键组成

  • Subject(抽象主题):定义真实主题(目标对象)和代理的共同接口(如业务方法),确保客户端可以无差别地使用两者。
  • RealSubject(真实主题):实现抽象主题接口,是代理真正要控制的对象(包含核心业务逻辑)。
  • Proxy(代理类):实现抽象主题接口,内部持有真实主题的引用,负责控制对真实主题的访问(如延迟初始化、权限检查),并在调用真实主题前后添加附加功能。
  • Client(客户端):通过代理对象间接调用真实主题的功能,无需直接与真实主题交互。

典型特征

  • 控制访问:代理可以限制或管理对真实对象的访问(如仅允许特定用户调用、限制调用频率)。
  • 功能增强:在不修改真实对象代码的前提下,通过代理添加额外行为(如缓存结果、记录日志、事务管理)。
  • 透明性:客户端无需感知代理的存在,代理与真实主题接口一致,调用方式相同。

适用场景

  • 远程代理:为位于不同地址空间的对象提供本地代表(如RPC调用、微服务网关)。
  • 虚拟代理:延迟创建开销大的对象(如图片懒加载,先显示占位图,滚动到可视区域再加载真实图片)。
  • 保护代理:控制对敏感对象的访问权限(如用户登录后才能操作个人数据)。
  • 智能引用:在访问对象时附加额外操作(如引用计数、自动释放资源、缓存命中检查)。

三. 行为模式(Behavioral Patterns)——11种

这类模式负责对象间的高效沟通和职责委派。

包括:责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式。

1.责任链模式

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

  • 解耦:请求发送者无需知道具体由哪个对象处理请求
  • 链式处理:多个处理者(处理器)依次尝试处理请求,形成处理链条
  • 灵活分配:处理逻辑可以在运行时动态组合和调整

关键组成

  • Handler(抽象处理者):定义处理请求的接口,通常包含一个指向下一个处理者的引用
  • ConcreteHandler(具体处理者):实现具体的处理逻辑,决定是否处理请求或传递给下一个处理者
  • Client(客户端):组装责任链并提交请求

适用场景

  • 多级审批流程(如请假审批、费用报销)
  • 异常处理机制
  • 中间件/过滤器链(如Web请求处理)
  • 日志记录/审计链条
  • 事件处理系统

2.命令模式

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

“请求”封装成独立的命令对象,该对象包含执行操作所需的全部信息(如接收者方法参数等)。客户端不直接调用接收者的方法,而是通过命令对象间接调用,实现请求的解耦,并支持扩展功能(如排队、日志、撤销等)。

关键角色

  • Command(命令接口):定义执行操作的接口
  • ConcreteCommand(具体命令):实现命令接口,绑定接收者与操作
  • Receiver(接收者):真正执行操作的对象
  • Invoker(调用者):持有命令对象并触发执行
  • Client(客户端):创建命令对象并设置接收者

适用场景

  • 需要将请求调用者请求执行者解耦
  • 支持撤销/重做操作
  • 请求需要排队日志记录组合成宏命令
  • 典型应用:GUI按钮事件事务管理命令行解析

3.解释器模式

给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

  • 语言解释:为特定领域的语言或表达式定义解释规则
  • 文法表示:将语言的结构(语法/表达式)抽象成类结构
  • 递归解释:通过组合基础表达式来解释复杂表达式

关键组成

  • 抽象表达式(AbstractExpression):声明一个抽象的解释操作
  • 终结符表达式(TerminalExpression):实现与文法中的终结符相关的解释操作(如变量、常量)
  • 非终结符表达式(NonterminalExpression):实现文法规则的解释操作(如运算符、复合表达式)
  • 上下文(Context):包含解释器之外的一些全局信息(如变量值表)
  • 客户端(Client):构建表示该文法定义的语言中一个特定句子的抽象语法树,并调用解释操作

适用场景

  • 正则表达式解析
  • 数学表达式计算(如加减乘除、括号优先级)
  • SQL查询解析
  • 编程语言语法解释(如简易DSL)
  • 工作流/规则引擎中的条件判断

4.迭代器模式

提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。

  • 封装遍历:将集合的遍历逻辑从集合对象中分离出来,独立封装
  • 统一接口:为不同类型的集合提供一致的遍历方式
  • 隐藏细节:客户端无需知道集合的内部结构(如数组、链表等)

关键组成

  • Iterator(迭代器接口):定义遍历操作的接口(如hasNext()、next())
  • ConcreteIterator(具体迭代器):实现迭代器接口,记录当前遍历位置并负责具体遍历逻辑
  • Aggregate(聚合接口):定义创建对应迭代器对象的接口(如createIterator())
  • ConcreteAggregate(具体聚合类):实现聚合接口,返回具体迭代器实例
  • Client(客户端):通过迭代器访问集合元素,无需直接操作集合内部结构

适用场景

  • 系统中对象之间存在复杂的引用关系(如UI组件间交互)
  • 多个类相互依赖,难以复用(通过中介者解耦)
  • 需要集中控制多个对象的交互逻辑(如聊天室、游戏中的角色协作)
  • 希望减少子类生成(通过中介者封装复杂条件分支)

5.中介者模式

用一个中介对象(中介者)来封装一系列对象(同事对象)的交互,使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

  • 集中控制交互:将多个对象(同事对象)之间的复杂交互逻辑从各个对象内部抽离出来,统一交给中介者对象管理,避免对象之间直接相互依赖。
  • 解耦同事对象:同事对象之间不再直接通信,而是通过中介者进行消息传递,降低对象之间的耦合度,使系统更易于维护和扩展。
  • 统一协调逻辑:中介者负责协调各个同事对象之间的行为,将原本分散在各个对象中的交互逻辑集中管理,便于复用和修改。

关键组成

  • Mediator(抽象中介者):定义同事对象和中介者之间的交互接口,通常包含一个或多个方法,用于处理同事对象之间的通信。
  • ConcreteMediator(具体中介者):实现抽象中介者接口,它包含对各个同事对象的引用,负责协调同事对象之间的交互,处理它们之间的消息传递和业务逻辑。
  • Colleague(抽象同事类):定义同事对象的接口,通常包含一个指向中介者的引用,同事对象通过该引用与中介者进行通信。
  • ConcreteColleague(具体同事类):实现抽象同事类接口,每个具体同事类都有自己独立的功能,当需要与其他同事对象交互时,通过调用中介者的方法来实现,而不是直接与其他同事对象通信。

典型特征

  • 低耦合:同事对象之间不直接依赖,而是通过中介者间接交互,减少了对象之间的直接耦合,提高了系统的灵活性和可维护性。
  • 集中管理:中介者将同事对象之间的交互逻辑集中管理,使得交互规则的变化只需要修改中介者,而不需要修改各个同事对象。
  • 协调协作:中介者负责协调多个同事对象之间的协作,确保它们按照一定的规则和顺序进行交互,从而实现复杂的业务逻辑。

适用场景

  • 多对象间复杂交互:当系统中有多个对象,它们之间存在复杂的交互关系,且这些交互关系相互交织,难以维护时,可以使用中介者模式来简化交互逻辑。
  • 对象间依赖解耦:希望减少对象之间的直接依赖,使对象可以独立变化和复用,避免因对象之间的紧密耦合而导致系统难以扩展和维护。
  • 集中控制交互规则:当一个系统中多个对象之间的交互规则需要集中管理和统一协调时,中介者可以将这些规则封装起来,方便管理和修改。

6.备忘录模式

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便之后可以将该对象恢复到原先保存的状态。

  • 状态保存:将对象的关键状态外部化存储,支持后续恢复
  • 封装保护:不直接暴露对象内部实现细节,通过备忘录对象间接操作状态
  • 控制恢复:提供撤销/回滚能力,维持对象状态的可追溯性

关键组成

  • Originator(原发器):需要保存状态的对象(如游戏角色、文档编辑器),提供创建备忘录和从备忘录恢复状态的方法
  • Memento(备忘录):存储原发器的内部状态快照(仅原发器可访问其私有数据)
  • Caretaker(管理者):负责保存和管理备忘录(如撤销栈),不操作或检查备忘录内容

适用场景

  • 需要撤销/重做功能(如文本编辑器、绘图软件)
  • 游戏存档/角色状态保存(如血量、位置等关键数据)
  • 事务回滚机制(如数据库操作前的状态备份)
  • 配置变更前的快照(如系统参数临时调整)

7.观察者模式

定义对象间的一种一对多的依赖关系,当一个对象(被观察者)的状态发生改变时,所有依赖于它的对象(观察者)都会得到通知并自动更新。

  • 解耦通知:被观察者和观察者之间松耦合,被观察者无需知道观察者的具体实现
  • 事件驱动:当被观察者状态变化时,主动通知所有注册的观察者
  • 动态订阅:观察者可以自由订阅或取消订阅被观察者的状态变更

关键组成

  • Subject(被观察者/主题):维护观察者列表,提供注册/删除观察者通知观察者的方法
  • Observer(观察者接口):定义更新方法(如update()),供被观察者调用
  • ConcreteSubject(具体被观察者):实现主题接口,存储具体状态,状态变化时通知观察者
  • ConcreteObserver(具体观察者):实现观察者接口,接收通知并执行相应逻辑(如更新UI、记录日志)

典型特征

  • 支持广播通信(一个被观察者对应多个观察者)
  • 观察者可以动态增减,运行时灵活调整
  • 符合开闭原则(新增观察者无需修改被观察者代码)

适用场景

  • 事件监听系统(如GUI按钮点击事件、前端Vue/React响应式数据)
  • 实时数据同步(如股票价格变动通知多个投资者)
  • 消息队列/发布-订阅模型(如Kafka、RabbitMQ的消息分发)
  • 游戏开发(如角色死亡事件触发多个系统响应)

8.状态模式

允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。

  • 状态驱动行为:对象的行为随其内部状态动态变化,不同状态下执行不同逻辑
  • 封装状态逻辑:将每个状态的行为封装到独立的类中,避免大量条件判断语句(如if-else/switch-case)
  • 显式状态转换:通过状态对象自身控制状态转移(符合"好莱坞原则":高层模块不主动调用底层,由底层通知高层)

关键组成

  • Context(上下文/环境类):维护一个当前状态对象,定义客户端需要的接口,并将状态相关请求委托给当前状态处理
  • State(状态接口):定义所有具体状态类共有的行为方法(如处理请求的方法)
  • ConcreteState(具体状态类):实现状态接口,封装特定状态下的行为状态转换规则

典型特征

  • 每个状态是独立的类,符合单一职责原则
  • 状态切换逻辑分散在各个状态类中,避免庞大的条件分支
  • 新增状态只需添加新类,无需修改现有状态类(开闭原则)

适用场景

  • 对象行为依赖复杂状态(如订单状态:待支付→已支付→已发货→已完成)
  • 存在大量与状态相关的条件语句(需要用状态类替代多重判断)
  • 状态转换有明确规则(如游戏角色的不同行动状态:站立、行走、攻击)
  • 需要动态切换对象行为(如网络连接状态:连接中/已连接/断开)

9.策略模式

定义一系列算法,将每个算法分别封装起来,使它们可以互相替换,且算法的变化不会影响使用算法的客户端。

  • 算法封装:将不同的业务规则或算法独立封装成策略类,彼此之间可灵活替换
  • 解耦调用:客户端只依赖抽象策略接口,不直接依赖具体算法实现
  • 运行时切换:可在程序运行期间动态选择不同的策略

关键组成

  • Context(上下文/环境类):持有一个策略对象的引用,提供统一调用接口,并将具体业务逻辑委托给策略对象执行
  • Strategy(策略接口):定义所有具体策略类必须实现的公共方法(通常是执行算法的方法)
  • ConcreteStrategy(具体策略类):实现策略接口,封装具体的算法实现或业务规则

典型特征

  • 避免使用大量的条件判断语句(如if-else/switch-case)来选择不同算法
  • 每个策略类只关注一种算法实现,符合单一职责原则
  • 新增策略时只需添加新类,无需修改现有代码(符合开闭原则)

适用场景

1. 一个系统需要在多种算法中动态选择一种(如排序算法:冒泡/快速/归并排序)

2. 业务规则经常变化或有多种实现方式(如电商促销策略:满减/折扣/赠品)

3. 需要隔离复杂算法的实现细节(如支付方式:支付宝/微信/银行卡支付)

4. 同一功能的不同变体需要灵活切换(如数据压缩算法:ZIP/RAR/7z)

10.模板方法模式

定义一个操作中的算法骨架,而将一些步骤延迟到子类中实现。模板方法使得子类可以不改变算法结构的情况下,重新定义算法中的某些特定步骤。

  • 固定流程:在父类中定义算法的整体步骤和执行顺序(即“模板”),保证流程一致性
  • 灵活扩展:将某些步骤的具体实现延迟到子类,允许子类按需重写这些步骤
  • 代码复用:通过继承复用父类的通用逻辑,避免重复编写相同流程代码

关键组成

  • AbstractClass(抽象类):定义算法的骨架(模板方法),包含基本方法(具体实现)抽象方法(待子类实现)
  • ConcreteClass(具体子类):实现抽象类中的抽象方法,定制模板中的特定步骤

典型特征

  • 模板方法(通常是final或非虚方法)定义了算法的不可变执行流程
  • 通过抽象方法/钩子方法(Hook)让子类参与特定步骤的实现
  • 符合“好莱坞原则”(Don't call us, we'll call you)——父类调用子类方法,而非子类主动调用父类

适用场景

1. 多个类有相同的行为流程,但部分步骤实现不同(如不同文档的解析流程:读取→解析→保存,但解析逻辑各异)

2. 需要控制子类扩展点,避免修改核心流程(如游戏中的战斗流程:准备→战斗→结算,但不同职业的战斗逻辑不同)

3. 重构代码时,将重复的流程提取到父类(减少子类中的冗余代码)

11.访问者模式

将算法与对象结构分离,使得可以在不修改现有对象结构的前提下,定义作用于这些对象的新操作。

  • 双重分派:通过元素对象接受访问者,再由访问者调用元素的具体方法,实现基于对象类型和操作类型的动态绑定。
  • 分离关注点:将数据结构(元素类)与对数据的操作(访问者类)解耦,使操作能独立变化而不影响元素类。
  • 扩展操作灵活:新增操作只需添加新的访问者类,无需修改现有的元素类(符合开闭原则)。

关键组成

  • Element(元素接口/抽象类):定义一个accept方法,接受访问者对象作为参数(核心的双分派入口)。
  • ConcreteElement(具体元素类):实现元素接口,定义自身的业务数据,并在accept方法中调用访问者的对应方法(如visitor.visit(this))。
  • Visitor(访问者接口):为每个具体元素类声明一个visit方法,定义对这些元素的操作逻辑。
  • ConcreteVisitor(具体访问者类):实现访问者接口,在visit方法中实现针对具体元素的操作(如打印、计算、统计等)。
  • ObjectStructure(对象结构,可选):维护元素集合,提供遍历元素并接受访问者的方法(如列表、树等容器)。

典型特征

  • 操作与结构分离:元素的类结构稳定,而操作(访问者)可灵活扩展。
  • 双分派机制:通过元素调用访问者,再由访问者反向调用元素方法,实现基于运行时类型的动态处理。
  • 适合稳定结构:当元素类结构频繁变动时,频繁新增访问者会导致类爆炸(需权衡使用)。

适用场景

  • 需要对复杂对象结构(如组合树、图)执行不相关的多种操作(如编译器的语法树分析:类型检查、代码生成、优化等)。
  • 对象结构稳定,但经常需要在此结构上定义新的操作(如文档处理:对文本、图片、表格等元素新增渲染、导出等操作)。
  • 需要集中相关操作逻辑,避免污染元素类(如电商订单的多种统计:总价计算、优惠分析、物流统计等)。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一. 创建型模式(Creational Patterns)——5种
    • 1.工厂方法模式
    • 2.抽象工厂模式
    • 3.建造者模式
    • 4.原型模式
    • 5.单例模式
  • 二. 结构型模式(Structural Patterns)——7种
    • 1.适配器模式
    • 2.桥接模式
    • 3.组合模式
    • 4.装饰器模式
    • 5.外观模式
    • 6.享元模式
    • 7.代理模式
  • 三. 行为模式(Behavioral Patterns)——11种
    • 1.责任链模式
    • 2.命令模式
    • 3.解释器模式
    • 4.迭代器模式
    • 5.中介者模式
    • 6.备忘录模式
    • 7.观察者模式
    • 8.状态模式
    • 9.策略模式
    • 10.模板方法模式
    • 11.访问者模式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档