设计模式一览表
设计模式是软件开发中经验证的通用解决方案,按核心功能分为创建型、结构型、行为型三大类。以下表格聚焦核心信息,便于快速选型和理解:
| 模式分类 | 模式名称(中英文) | 核心意图 | 适用场景 | 核心优点 | 潜在缺点 |
|---|---|---|---|---|---|
| 创建型 | 单例模式(Singleton) | 确保一个类仅有一个实例,并提供全局访问点 | 配置文件、日志对象、数据库连接池、线程池 | 节省资源、全局统一访问 | 违反单一职责、扩展性差、多线程需特殊处理 |
| 工厂方法模式(Factory Method) | 定义创建对象的接口,由子类决定实例化哪个类(延迟实例化) | 产品种类多、需灵活扩展产品族(如支付方式:微信/支付宝/银联) | 符合开闭原则、解耦产品创建与使用 | 增加类数量、系统复杂度上升 | |
| 抽象工厂模式(Abstract Factory) | 提供接口创建一系列相关/依赖对象,无需指定具体类 | 需创建多个产品族(如操作系统+UI组件:Windows/按钮/菜单、Mac/按钮/菜单) | 保证产品族一致性、符合开闭原则 | 扩展新产品困难(需修改工厂接口) | |
| 建造者模式(Builder) | 将复杂对象的构建与表示分离,同一构建过程可创建不同表示 | 复杂对象构建(如订单:基础信息+商品+支付+物流)、生成器工具 | 解耦构建与表示、灵活控制构建步骤 | 增加类数量、构建逻辑分散 | |
| 原型模式(Prototype) | 通过复制现有对象(原型)创建新对象,避免重复初始化 | 对象创建成本高(如数据库查询结果)、需批量创建相似对象 | 提高创建效率、简化创建逻辑 | 深拷贝复杂对象时实现难度大 | |
| 结构型 | 适配器模式(Adapter) | 将一个类的接口转换成客户端期望的另一个接口,解决接口不兼容问题 | 集成第三方库(接口不匹配)、旧系统改造(兼容新接口) | 复用现有代码、解耦客户端与适配者 | 增加系统复杂度、适配逻辑可能冗余 |
| 装饰器模式(Decorator) | 动态给对象添加额外职责,不改变原类结构(替代继承) | 功能扩展(如日志、缓存、权限校验)、灵活组合功能 | 无侵入扩展、符合开闭原则、组合灵活 | 多层装饰器可能导致调试复杂 | |
| 代理模式(Proxy) | 为其他对象提供代理,控制对原对象的访问(权限、缓存、延迟加载) | 远程服务调用(RPC)、缓存代理、权限控制、延迟加载大对象 | 保护原对象、增强功能、解耦客户端与原对象 | 增加中间层、可能降低响应速度 | |
| 组合模式(Composite) | 将对象组合成树形结构,统一处理单个对象和组合对象(部分-整体) | 树形结构场景(文件系统、菜单、组织架构) | 统一访问接口、简化客户端逻辑、便于扩展 | 叶子/组合节点职责划分需清晰 | |
| 外观模式(Facade) | 为子系统提供统一的高层接口,简化子系统使用 | 复杂系统集成(如支付系统:整合支付、退款、对账)、第三方API封装 | 简化接口、降低耦合、提高可用性 | 外观类易成"上帝类"(职责过重) | |
| 桥接模式(Bridge) | 将抽象与实现分离,使两者可独立变化(解耦多维度变化) | 多维度变化场景(如消息通知:渠道(短信/邮件)+类型(验证码/公告)) | 解耦多维度变化、符合开闭原则、扩展性强 | 增加系统复杂度、设计难度上升 | |
| 享元模式(Flyweight) | 共享细粒度对象,减少内存占用(复用相似对象) | 大量相似对象场景(游戏敌人、字符渲染、缓存池) | 节省内存、提高性能 | 增加共享逻辑复杂度、需维护享元池 | |
| 行为型 | 策略模式(Strategy) | 定义一系列算法,封装并替换它们,使算法独立于客户端变化 | 多种算法可选(排序、折扣计算、支付方式)、需动态切换算法 | 算法解耦、灵活切换、符合开闭原则 | 增加策略类数量、客户端需了解策略差异 |
| 观察者模式(Observer) | 定义一对多依赖,一个对象变化时,所有依赖对象自动更新 | 事件通知(UI更新、消息订阅、日志监听)、发布-订阅系统 | 解耦观察者与被观察者、支持动态订阅 | 通知顺序不确定、可能导致循环依赖 | |
| 命令模式(Command) | 将请求封装为对象,解耦请求发送者与接收者(支持撤销、队列) | 操作记录/撤销(文本编辑器、游戏存档)、任务队列、远程命令执行 | 解耦发送者与接收者、支持命令扩展 | 增加类数量、命令逻辑分散 | |
| 迭代器模式(Iterator) | 提供方法顺序访问聚合对象元素,无需暴露内部结构 | 遍历集合对象(列表、字典、自定义容器)、统一遍历接口 | 统一遍历接口、解耦遍历与集合 | 增加迭代器类、简单集合无需使用 | |
| 模板方法模式(Template Method) | 定义算法骨架,将步骤延迟到子类实现(固定流程,灵活定制步骤) | 固定流程场景(测试用例、报表生成、流程审批) | 统一算法骨架、复用公共逻辑、符合开闭原则 | 子类可能过多、骨架修改影响所有子类 | |
| 状态模式(State) | 对象内部状态变化时改变行为,使对象看似修改了类 | 状态多且切换复杂(如订单:待支付→已支付→已发货→已完成) | 状态逻辑封装、简化条件判断、扩展性强 | 增加状态类数量、状态转换逻辑分散 | |
| 责任链模式(Chain of Responsibility) | 为请求创建处理链,请求在链上传递直到被处理 | 多级审批(请假、报销)、日志分级处理、异常处理链 | 解耦请求发送者与接收者、灵活调整链结构 | 请求可能未被处理、调试难度大 |
设计模式通用核心原则
设计模式的本质是遵循"高内聚、低耦合"的软件设计目标,以下是所有设计模式通用的核心原则,覆盖SOLID五大核心准则及通用设计思想:
1. 单一职责原则(Single Responsibility Principle, SRP)
一个类/模块仅承担一个明确的职责,职责边界清晰。当需求变化时,仅需修改对应职责的代码,减少改动带来的连锁影响,是所有设计原则的基础。
2. 开闭原则(Open/Closed Principle, OCP)
软件实体(类、模块、函数)对扩展开放,对修改关闭。即通过新增代码(如子类、新策略、新装饰器)实现功能扩展,而非修改已有稳定代码,是设计模式的核心目标。
3. 里氏替换原则(Liskov Substitution Principle, LSP)
子类可以无缝替换父类的位置且不影响程序正确性。子类需遵循父类的行为约定,仅扩展功能而非修改父类核心逻辑,是继承和多态的基础准则。
4. 接口隔离原则(Interface Segregation Principle, ISP)
客户端不应依赖不需要的接口,需将庞大的通用接口拆分为粒度更细的专用接口。避免客户端被迫实现无关方法,降低接口与实现的耦合度。
5. 依赖倒置原则(Dependency Inversion Principle, DIP)
高层模块不依赖低层模块的具体实现,两者均依赖抽象;抽象不依赖细节,细节依赖抽象。通过接口/抽象类解耦模块间的依赖,提升系统扩展性。
6. 迪米特法则(Law of Demeter, LoD)/最小知识原则
一个对象应尽可能少地了解其他对象,仅与直接关联的对象交互(如外观模式封装子系统、代理模式隔离原对象)。减少对象间的耦合,降低系统维护成本。
7. 优先使用组合/聚合,而非继承
组合/聚合的灵活性远高于继承,可动态调整对象间的关系(如装饰器、桥接、代理模式均基于组合);继承是静态的,易导致类层级臃肿、耦合过高。
8. 封装变化点
识别系统中易变化的部分并封装,将不变部分与变化部分分离(如策略模式封装算法变化、状态模式封装状态变化、工厂模式封装对象创建变化)。
9. 针对接口编程,而非针对实现编程
客户端仅依赖接口/抽象类定义的行为,不依赖具体实现类。使客户端与实现解耦,便于替换不同实现(如工厂方法、策略模式均体现此原则)。
10. 避免过度设计
设计模式是"解决方案"而非"必选项",需匹配业务复杂度。简单场景下(如仅需创建单个对象、简单遍历集合)无需强行使用设计模式,优先保证代码可读性和可维护性。