概述
1. 设计模式的核心价值
设计模式(Design Pattern)是软件开发领域经过长期实践验证的最佳解决方案模板,针对开发过程中高频出现的通用问题,提供了标准化、可复用的设计思路。它并非现成代码,而是一套沉淀后的设计思想,能有效提升代码的可维护性、扩展性和可读性,帮助开发者规避重复踩坑,同时降低团队协作的沟通成本。
2. 设计模式的提出背景
1994 年,Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著《Design Patterns - Elements of Reusable Object-Oriented Software》(中文译名:《设计模式 - 可复用的面向对象软件元素》),首次系统提出软件开发中的设计模式概念。四位作者被业界合称为 GOF(Gang of Four,四人帮),其提出的 23 种设计模式成为该领域的经典理论基础,至今仍被广泛应用。
3. 设计模式的核心设计原则
设计模式的本质是对面向对象设计原则的落地实践,核心原则包括:
- 对接口编程,而非对实现编程(依赖抽象,不依赖具体细节,降低耦合);
- 优先使用对象组合,而非继承(组合更灵活,可避免继承带来的强耦合与类爆炸问题);
- 单一职责原则(一个类仅负责一项功能,提升代码可读性与维护性)、开闭原则(对扩展开放,对修改关闭,降低迭代风险)、里氏替换原则(子类可替换父类且不影响程序正确性,保障继承体系的稳定性)。
4. PHP 设计模式的适用范围说明
设计模式的价值并非绝对,需结合语言特性与项目场景判断
- PHP 作为动态语言,部分静态语言(如 Java)中用于解决“类型限制”“接口强制约束”的模式(如抽象工厂模式的部分复杂场景),因语言特性天然规避了相关问题,无需强制使用;
- 但在中大型 PHP 项目中,核心设计模式仍是规范代码结构、提升开发效率的关键,其中常用且实用的模式包括:简单工厂模式(简化版的工厂模式,不在23种设计模式中)、工厂模式、单例模式、观察者模式、职责链模式、策略模式、装饰器模式、适配器模式、桥接模式、门面模式(共 10 种)。
设计模式的类型及详细说明
设计模式按核心功能分为三大类
1. 创建型模式
核心目标:隐藏对象创建逻辑,解耦对象实例化与使用场景,避免直接依赖 new 运算符,使程序在对象创建时更灵活、可扩展。
| 模式名称 | 定义 | PHP 适用场景与实践示例 |
|---|---|---|
| 工厂模式(Factory Pattern) | 定义一个创建对象的接口,将类的实例化延迟到其子类,由子类决定具体实例化哪个类,降低代码耦合。 | 场景:对象创建依赖参数或配置(如根据请求类型创建不同控制器、根据支付方式创建不同支付类); 示例: PaymentFactory::create('alipay') 生成支付宝支付实例,create('wechat') 生成微信支付实例。 |
| 抽象工厂模式(Abstract Factory Pattern) | 提供一个创建一系列相互依赖或关联对象的接口,无需指定具体类,支持整体替换“产品族”。 | 场景:大型项目的组件套装创建(如不同数据库的“连接池+查询器”组合、不同框架的“日志+缓存”组件); 注意:小型 PHP 项目可简化为工厂模式,避免过度设计。 |
| 单例模式(Singleton Pattern) | 保证一个类仅有一个实例,并提供全局访问点,避免重复创建资源消耗较大的对象(如数据库连接)。 | 场景:数据库连接、缓存实例、日志工具、配置管理类; 注意:PHP CLI 模式下,每次请求是独立进程,单例仅在当前进程有效,需避免误解。 |
| 建造者模式(Builder Pattern) | 将复杂对象的构建与表示分离,通过“建造者”封装分步构建逻辑,相同构建流程可生成不同表示。 | 场景:复杂对象创建(如包含多个可选参数的订单类、富文本编辑器的内容生成、多步骤表单提交后的对象组装); 优势:避免构造函数参数冗余,提升代码可读性。 |
| 原型模式(Prototype Pattern) | 用原型实例指定对象类型,通过拷贝(浅拷贝/深拷贝)原型创建新对象,提升创建效率(尤其适用于创建成本高的场景)。 | 场景:批量创建结构相似的对象(如批量生成用户账号、批量复制商品规格); 实现:PHP 中可通过 clone 关键字结合 __clone() 方法实现深拷贝。 |
2. 结构型模式
核心目标:优化类与对象的组合关系,通过继承、接口组合、对象关联等方式,实现功能复用或解耦,提升代码的灵活性与可扩展性。
| 模式名称 | 定义 | PHP 适用场景与实践示例 |
|---|---|---|
| 适配器模式(Adapter Pattern) | 将一个类的接口转换成客户端期望的另一个接口,解决因接口不兼容导致的类无法协同工作的问题。 | 场景:第三方工具类接口适配(如不同支付平台接口统一封装、旧系统接口兼容新代码); 示例:将第三方短信接口 SmsService::sendMsg($phone, $content) 适配为项目统一接口 MessageAdapter::send($phone, $content)。 |
| 桥接模式(Bridge Pattern) | 将抽象部分与实现部分分离(抽象类与具体实现类通过组合关联,而非继承),使两者可独立扩展,互不影响。 | 场景:多维度变化的功能模块(如“消息通知”:抽象层为通知类型(验证码、订单提醒),实现层为推送方式(短信、邮件、微信)); 优势:新增通知类型或推送方式时,无需修改原有代码,符合开闭原则。 |
| 组合模式(Composite Pattern) | 将对象组合成树形结构表示“部分-整体”层次关系,使客户端对单个对象和组合对象的使用逻辑一致。 | 场景:树形结构数据操作(如网站菜单管理、文件目录遍历、多级分类数据渲染); 示例:递归遍历并渲染“一级菜单→二级菜单→三级菜单”,客户端无需区分单个菜单与菜单组。 |
| 装饰器模式(Decorator Pattern) | 动态给对象添加额外职责,通过“装饰器包裹”目标对象实现功能扩展,比继承更灵活(避免类爆炸)。 | 场景:日志增强(给业务逻辑添加操作日志)、缓存装饰(给数据库查询添加缓存层)、权限控制(给接口添加权限校验); 实现:装饰器类与目标类实现同一接口,通过构造函数注入目标对象。 |
| 门面模式(Facade Pattern) | 为子系统的一组接口提供统一的高层接口,简化子系统调用,降低客户端与子系统的耦合。 | 场景:复杂系统的“入口封装”(如数据库操作层封装连接、查询、事务等接口,客户端仅需调用 DB::query($sql);优势:隐藏子系统复杂性,减少客户端代码量。 |
| 享元模式(Flyweight Pattern) | 通过共享技术高效支持大量细粒度对象,提取对象的公共状态(内部状态),减少内存消耗。 | 场景:大量相似对象场景(如商品列表的规格选项、网站中的图标元素、高频复用的配置项); 实现:PHP 中可结合静态数组或缓存存储共享对象,避免重复创建。 |
| 代理模式(Proxy Pattern) | 为目标对象提供代理对象,控制对目标对象的访问(如权限校验、延迟加载、日志记录、缓存拦截)。 | 场景:数据库查询代理(查询前先查缓存)、接口请求代理(统一权限校验)、大对象延迟加载(如按需加载大型文件对象); 示例: ProxyImage 代理 RealImage,仅在真正需要时才加载图片资源。 |
3. 行为型模式
核心目标:优化对象之间的通信方式,规范对象交互逻辑,降低对象间的耦合,提升代码的可维护性与扩展性。
| 模式名称 | 定义 | PHP 适用场景与实践示例 |
|---|---|---|
| 观察者模式(Observer Pattern) | 定义对象间的一对多依赖关系,当主题对象(被观察者)状态变化时,所有依赖它的观察者自动收到通知并更新。 | 场景:事件驱动编程(如框架钩子函数、订单状态变更后触发物流、通知、库存更新); 实现:PHP 中可通过 SplSubject 和 SplObserver 接口快速实现,或自定义主题与观察者接口。 |
| 模板模式(Template Pattern) | 定义算法的骨架(抽象类中的模板方法),将部分步骤延迟到子类实现,子类不改变算法结构即可重定义特定步骤。 | 场景:固定流程的差异化实现(如数据导出:统一流程为“查询数据→处理数据→导出文件”,子类实现 Excel/CSV/PDF 不同格式的导出步骤); 优势:复用公共流程,聚焦差异化逻辑。 |
| 命令模式(Command Pattern) | 将请求封装为对象,使请求可参数化、排队、记录日志或撤销,解耦请求发送者与接收者。 | 场景:任务队列(如异步邮件发送、定时任务)、操作日志与撤销(如编辑器的撤销功能、订单操作回滚); 示例:将“创建订单”“取消订单”封装为命令对象,放入队列中异步执行。 |
| 状态模式(State Pattern) | 允许对象在内部状态改变时改变其行为,将不同状态的逻辑封装到独立状态类中,避免大量 if-else 判断。 |
场景:状态频繁变化的对象(如订单状态流转:待支付→已支付→已发货→已完成→已取消); 优势:状态切换逻辑清晰,新增状态时仅需添加状态类,符合开闭原则。 |
| 职责链模式(Chain of Responsibility Pattern) | 将多个请求处理器连成一条链,请求沿链传递,直到某个处理器能处理它,避免请求发送者与接收者直接耦合。 | 场景:多规则处理请求(如表单验证、权限审批流程、接口请求过滤); 示例:用户注册信息校验链(手机号格式校验→邮箱格式校验→密码强度校验→用户名唯一性校验)。 |
| 解释器模式(Interpreter Pattern) | 定义一种语言的文法表示,创建解释器解释该语言中的句子,适用于自定义规则或简单表达式解析。 | 场景:自定义查询条件解析(如用户输入“价格>100 且 销量>500”)、模板引擎标签解析、简单规则引擎; 注意:复杂场景建议使用现成解析器(如 PHP 表达式解析库),避免重复造轮子。 |
| 中介者模式(Mediator Pattern) | 用中介对象封装一系列对象的交互,使对象无需直接通信,降低耦合,交互逻辑集中在中介者中。 | 场景:对象交互复杂的场景(如电商订单创建:中介者协调库存、支付、物流、通知模块的交互); 优势:减少对象间的直接依赖,便于维护交互逻辑。 |
| 访问者模式(Visitor Pattern) | 定义作用于对象结构中各元素的操作,在不改变元素类的前提下,可动态添加新操作(访问者)。 | 场景:对象结构稳定但操作需频繁扩展(如数据报表生成:同一组订单数据可生成销售额报表、用户消费报表、商品销量报表); 实现:元素类提供 accept 方法,接收访问者对象并调用其对应操作。 |
| 策略模式(Strategy Pattern) | 定义一系列算法,将每种算法封装为独立类,使算法可相互替换,且独立于使用它的客户端。 | 场景:可切换的业务逻辑(如支付方式选择、数据排序算法、图片压缩策略); 示例:订单支付时,可切换支付宝、微信、银行卡等不同支付策略,客户端无需关心具体实现。 |
| 备忘录模式(Memento Pattern) | 在不破坏封装的前提下,捕获对象的内部状态并保存到外部(备忘录),后续可将对象恢复到原先保存的状态。 | 场景:需要“状态回滚”的功能(如编辑器撤销、配置项历史版本恢复、游戏存档); 实现:备忘录类存储对象状态,发起人类负责创建和恢复备忘录,管理者类负责管理备忘录。 |
| 迭代器模式(Iterator Pattern) | 提供一种顺序访问聚合对象(如数组、集合)元素的方法,不暴露聚合对象的内部结构,支持不同遍历方式。 | 场景:自定义集合遍历(如分页数据集合、树形结构遍历、复杂数据结构(如链表)遍历); 实现:PHP 中可实现 Iterator 接口,使自定义集合兼容 foreach 语法。 |


