学完这篇,你能把 23 种设计模式按「创建 / 结构 / 行为」三类装进脑子,并知道每一种在 PHP 里最短怎么写、什么时候该用、什么时候是给自己找麻烦。
第一步:先分类,别死背 23 个名字
记住三句话就够了:
- 创建型 5 种(工厂方法、抽象工厂、单例、建造者、原型)——解决「对象从哪来」
- 结构型 7 种(适配器、桥接、组合、装饰器、外观、享元、代理)——解决「对象怎么拼」
- 行为型 11 种(责任链、命令、解释器、迭代器、中介者、备忘录、观察者、状态、策略、模板方法、访问者)——解决「对象怎么配合」
分类记住,剩下的就是查字典的活儿。
第二步:创建型——重点掌握 2 个
单例(全局唯一入口,比如数据库连接):
final class Db
{
private static ?self $instance = null;
private function __construct() {}
private function __clone() {}
public static function get(): self
{
return self::$instance ??= new self();
}
}
建造者(链式拼装复杂对象,比如 SQL 构造器):
final class QueryBuilder
{
private array $parts = [];
public function where(string $w): self { $this->parts[] = "WHERE {$w}"; return $this; }
public function limit(int $n): self { $this->parts[] = "LIMIT {$n}"; return $this; }
public function build(): string { return implode(' ', $this->parts); }
}
其余三个:工厂方法(子类决定实例化哪个类)、抽象工厂(一整族产品一起换)、原型(`clone` 复制已有对象,省掉重复初始化)。
注意:PHP 是「每请求一个进程」,单例只在本次请求内唯一,别把它当跨请求缓存用。
第三步:结构型——装饰器和代理最容易混
装饰器(不改原类,层层加功能):
interface Notifier { public function send(string $m): void; }
class BaseNotifier implements Notifier {
public function send(string $m): void { echo $m; }
}
class LogNotifier implements Notifier {
public function __construct(private Notifier $inner) {}
public function send(string $m): void { error_log($m); $this->inner->send($m); }
}
(new LogNotifier(new BaseNotifier))->send('hello');
其余六个一句话记法:适配器统一不同接口,外观包一层简化调用,组合处理树形结构(版块/子分类就是典型),桥接把抽象和实现拆成两条继承线,享元用对象池复用重复对象,代理在真实对象前拦一道。
注意:装饰器是「增强功能」,代理是「控制访问」。分不清就先问自己:加这层是为了多做点事,还是为了少让人碰?
注意:上面用了构造器属性提升(PHP 8.0+),PHP 7.4 环境改成手动 `$this->inner = $inner;` 即可。
第四步:行为型——实际项目里最常用的三个
策略(把 if-else 换成可替换算法):
interface Pay { public function pay(float $n): string; }
class Alipay implements Pay { public function pay(float $n): string { return "alipay:{$n}"; } }
class Wechat implements Pay { public function pay(float $n): string { return "wechat:{$n}"; } }
class Order {
public function __construct(private Pay $pay) {}
public function submit(float $n): string { return $this->pay->pay($n); }
}
观察者(事件/钩子机制,插件系统的地基):
class Hook
{
private array $listeners = [];
public function on(string $event, callable $fn): void { $this->listeners[$event][] = $fn; }
public function fire(string $event, ...$args): void {
foreach ($this->listeners[$event] ?? [] as $fn) { $fn(...$args); }
}
}
责任链(中间件、多级校验)。
其余:命令(把操作封装成对象,可撤销)、状态(把状态机从 switch 里救出来)、模板方法(父类定骨架、子类填细节)、迭代器(`Iterator`/`Generator` 遍历)、中介者(多方交互收口到一个中心)、备忘录(快照回滚)、访问者(对稳定结构加新操作)、解释器(表达式解析,用得最少)。
无框架的轻量系统基本都靠钩子跑插件,比如 Clara BBS 那套 156 个运行时钩子,本质就是观察者模式加一层优先级调度,保存即生效。
第五步:落地口诀
- 新对象有分支 → 工厂
- 对象要全局唯一 → 单例(能依赖注入就别用)
- 功能要叠加 → 装饰器
- 算法要换 → 策略
- 一对多通知 → 观察者
- 多级处理 → 责任链
- 剩下 17 种,遇到场景再翻字典
注意:模式是「发现」出来的,不是「设计」出来的。写完一版觉得别扭,再回头看它像哪个模式——反过来先挑模式套代码,通常得到一堆没必要的接口和抽象类。
小结
- 23 种按创建 / 结构 / 行为三类分组记忆,比按字母背强十倍
- PHP 里最高频的是:单例、工厂方法、装饰器、策略、观察者、责任链
- 每引入一个模式就多一层抽象,先能跑通,再谈解耦
- 单例在 PHP 里是请求级,不是进程级
- 装饰器管增强、代理管访问、适配器管兼容,别混着用