PHP设计模式
🧱 一、设计模式的基本概念
设计模式 是在软件开发中被反复使用的、经过验证的解决特定问题的代码结构或思维方式。 它不是现成的代码,而是一种“最佳实践”。
设计模式的作用:
- 提高代码复用性、可维护性;
- 降低耦合、增强扩展性;
- 让团队协作更高效(统一思维模型)。
🏗️ 二、设计模式分类总览
| 类型 | 模式名称 | 简介 |
|---|---|---|
| 创建型(Creational) | 单例(Singleton) | 全局唯一实例 |
| 工厂方法(Factory Method) | 让子类决定创建哪种对象 | |
| 抽象工厂(Abstract Factory) | 生产一族相关对象 | |
| 建造者(Builder) | 分步骤构建复杂对象 | |
| 原型(Prototype) | 通过克隆创建对象 | |
| 结构型(Structural) | 适配器(Adapter) | 统一不同接口 |
| 装饰器(Decorator) | 动态增强对象功能 | |
| 代理(Proxy) | 控制对象访问 | |
| 外观(Facade) | 提供统一接口封装复杂子系统 | |
| 桥接(Bridge) | 分离抽象与实现 | |
| 组合(Composite) | 树状结构统一操作 | |
| 享元(Flyweight) | 共享细粒度对象 | |
| 行为型(Behavioral) | 观察者(Observer) | 订阅通知机制 |
| 策略(Strategy) | 可替换算法 | |
| 模板方法(Template Method) | 定义算法框架 | |
| 命令(Command) | 将操作封装为对象 | |
| 责任链(Chain of Responsibility) | 依次处理请求 | |
| 状态(State) | 状态驱动行为变化 | |
| 迭代器(Iterator) | 顺序访问集合元素 | |
| 中介者(Mediator) | 集中管理对象交互 | |
| 解释器(Interpreter) | 自定义语言语法解释 | |
| 备忘录(Memento) | 保存与恢复对象状态 | |
| 访问者(Visitor) | 分离算法与数据结构 |
🧩 三、常用模式详解(含 PHP 示例)
🧱 一、创建型模式(Creational Patterns)
1. 单例模式(Singleton Pattern)
定义: 保证一个类只有一个实例,并提供一个全局访问点。
意图: 在系统中只需要一个对象来协调行为,例如日志、配置、数据库连接池。
PHP 示例:
<?php
class Singleton {
private static ?Singleton $instance = null;
private function __construct() {} // 禁止外部实例化
private function __clone() {} // 禁止克隆
private function __wakeup() {} // 禁止反序列化
public static function getInstance(): Singleton {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function log(string $msg): void {
echo "[LOG]: " . $msg . PHP_EOL;
}
}
// 使用
$logger1 = Singleton::getInstance();
$logger2 = Singleton::getInstance();
var_dump($logger1 === $logger2); // true
$logger1->log("系统启动完成");
?>应用场景:
- 日志记录类
- 数据库连接管理
- 配置中心
优缺点:
- ✅ 优点:节省资源;集中管理;全局访问
- ❌ 缺点:难以测试;隐藏依赖;多线程环境需加锁
2. 工厂方法模式(Factory Method Pattern)
定义: 定义一个创建对象的接口,让子类决定实例化哪个类。
意图: 将对象创建的责任交给子类,从而让代码更具扩展性。
PHP 示例:
<?php
interface Product {
public function getName(): string;
}
class Car implements Product {
public function getName(): string { return "Car"; }
}
class Bike implements Product {
public function getName(): string { return "Bike"; }
}
abstract class Creator {
abstract public function createProduct(): Product;
public function deliver(): string {
$product = $this->createProduct();
return "Delivering: " . $product->getName();
}
}
class CarFactory extends Creator {
public function createProduct(): Product { return new Car(); }
}
class BikeFactory extends Creator {
public function createProduct(): Product { return new Bike(); }
}
// 使用
$factory = new CarFactory();
echo $factory->deliver();
?>应用场景:
- 框架根据类型动态生成不同对象
- 创建日志对象、数据库驱动等
优缺点:
- ✅ 优点:符合开闭原则、易于扩展
- ❌ 缺点:类数量增多、结构复杂
3. 抽象工厂模式(Abstract Factory Pattern)
定义: 提供一个接口,用于创建相关或依赖对象的家族,而无需指定具体类。
意图: 用于生成一系列相关产品对象(如一整套 UI 组件)。
PHP 示例:
<?php
// 抽象产品族
interface Button {
public function render(): string;
}
interface Checkbox {
public function render(): string;
}
// 具体产品
class WinButton implements Button {
public function render(): string { return "Windows Button"; }
}
class MacButton implements Button {
public function render(): string { return "Mac Button"; }
}
class WinCheckbox implements Checkbox {
public function render(): string { return "Windows Checkbox"; }
}
class MacCheckbox implements Checkbox {
public function render(): string { return "Mac Checkbox"; }
}
// 抽象工厂
interface GUIFactory {
public function createButton(): Button;
public function createCheckbox(): Checkbox;
}
// 具体工厂
class WinFactory implements GUIFactory {
public function createButton(): Button { return new WinButton(); }
public function createCheckbox(): Checkbox { return new WinCheckbox(); }
}
class MacFactory implements GUIFactory {
public function createButton(): Button { return new MacButton(); }
public function createCheckbox(): Checkbox { return new MacCheckbox(); }
}
// 使用
function renderUI(GUIFactory $factory) {
echo $factory->createButton()->render() . PHP_EOL;
echo $factory->createCheckbox()->render() . PHP_EOL;
}
renderUI(new MacFactory());
?>应用场景:
- UI库跨平台(Windows / Mac)
- 数据库访问层(MySQL / PostgreSQL)
优缺点:
- ✅ 优点:保证产品族一致性;易于切换产品系列
- ❌ 缺点:新增产品族困难;结构复杂
4. 建造者模式(Builder Pattern)
定义: 将复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。
意图: 分步骤创建复杂对象。
PHP 示例:
<?php
class Meal {
private array $items = [];
public function addItem(string $item) { $this->items[] = $item; }
public function showItems() { echo implode(", ", $this->items) . PHP_EOL; }
}
interface MealBuilder {
public function addBurger(): void;
public function addDrink(): void;
public function getMeal(): Meal;
}
class VegMealBuilder implements MealBuilder {
private Meal $meal;
public function __construct() { $this->meal = new Meal(); }
public function addBurger(): void { $this->meal->addItem("Veg Burger"); }
public function addDrink(): void { $this->meal->addItem("Juice"); }
public function getMeal(): Meal { return $this->meal; }
}
class Director {
public function buildMeal(MealBuilder $builder): Meal {
$builder->addBurger();
$builder->addDrink();
return $builder->getMeal();
}
}
// 使用
$director = new Director();
$builder = new VegMealBuilder();
$meal = $director->buildMeal($builder);
$meal->showItems();
?>应用场景:
- 创建复杂对象(例如配置对象、报表生成、订单生成)
- 一步步创建对象
优缺点:
- ✅ 优点:构建过程独立、复用性强
- ❌ 缺点:增加代码复杂度
5. 原型模式(Prototype Pattern)
定义: 通过复制现有对象来创建新对象,而不是通过实例化类。
意图: 用于创建代价高昂的对象副本。
PHP 示例:
<?php
class Document {
public string $title;
public array $pages = [];
public function __construct(string $title) {
$this->title = $title;
}
public function addPage(string $content) {
$this->pages[] = $content;
}
public function __clone() {
// 深拷贝逻辑
$this->pages = array_map(fn($p) => $p, $this->pages);
}
}
// 使用
$doc1 = new Document("Design Pattern Guide");
$doc1->addPage("Singleton Pattern");
$doc1->addPage("Factory Pattern");
$doc2 = clone $doc1;
$doc2->title = "Copied Document";
$doc2->addPage("Extra Notes");
print_r($doc1);
print_r($doc2);
?>应用场景:
- 创建对象代价高昂(如复杂初始化)
- 动态复制对象状态
优缺点:
- ✅ 优点:提高性能、简化创建逻辑
- ❌ 缺点:深拷贝实现复杂、可能引发引用问题
🧩 二、结构型模式(Structural Patterns)
6. 适配器模式(Adapter Pattern)
定义: 将一个类的接口转换为客户端期望的另一个接口,使原本不兼容的类可以协同工作。
意图: 兼容不同接口的类,使原有代码无需修改即可使用新组件。
PHP 示例:
<?php
// 旧接口
class OldPrinter {
public function printOld(string $text) {
echo "Old printer prints: $text\n";
}
}
// 新接口
interface NewPrinter {
public function print(string $text): void;
}
// 适配器
class PrinterAdapter implements NewPrinter {
private OldPrinter $oldPrinter;
public function __construct(OldPrinter $oldPrinter) {
$this->oldPrinter = $oldPrinter;
}
public function print(string $text): void {
$this->oldPrinter->printOld($text);
}
}
// 使用
$adapter = new PrinterAdapter(new OldPrinter());
$adapter->print("Hello Adapter!");
?>应用场景:
- 系统需要使用旧接口类但接口不兼容
- 第三方库接口与系统接口不一致
优缺点:
- ✅ 优点:提高兼容性、复用旧代码
- ❌ 缺点:增加代码复杂度
7. 桥接模式(Bridge Pattern)
定义: 将抽象部分与实现部分分离,使它们都可以独立变化。
意图: 解耦抽象与实现,提高灵活性。
PHP 示例:
<?php
interface Device {
public function turnOn(): void;
public function turnOff(): void;
}
class TV implements Device {
public function turnOn(): void { echo "TV On\n"; }
public function turnOff(): void { echo "TV Off\n"; }
}
class Radio implements Device {
public function turnOn(): void { echo "Radio On\n"; }
public function turnOff(): void { echo "Radio Off\n"; }
}
class Remote {
protected Device $device;
public function __construct(Device $device) {
$this->device = $device;
}
public function togglePower(): void {
$this->device->turnOn();
}
}
// 使用
$remote = new Remote(new TV());
$remote->togglePower();
?>应用场景:
- 多平台、多设备支持(UI、驱动)
- 分离变化维度(如设备类型与控制逻辑)
优缺点:
- ✅ 优点:抽象与实现独立扩展
- ❌ 缺点:增加类数量与结构复杂度
8. 组合模式(Composite Pattern)
定义: 将对象组合成树形结构以表示“部分—整体”的层次结构。
意图: 让客户端统一对待单个对象和对象集合。
PHP 示例:
<?php
interface Component {
public function show(int $depth = 0): void;
}
class Leaf implements Component {
private string $name;
public function __construct(string $name) { $this->name = $name; }
public function show(int $depth = 0): void {
echo str_repeat("-", $depth) . $this->name . PHP_EOL;
}
}
class Composite implements Component {
private string $name;
private array $children = [];
public function __construct(string $name) { $this->name = $name; }
public function add(Component $component): void { $this->children[] = $component; }
public function show(int $depth = 0): void {
echo str_repeat("-", $depth) . $this->name . PHP_EOL;
foreach ($this->children as $child) {
$child->show($depth + 2);
}
}
}
// 使用
$root = new Composite("root");
$root->add(new Leaf("Leaf A"));
$sub = new Composite("Branch B");
$sub->add(new Leaf("Leaf C"));
$root->add($sub);
$root->show();
?>应用场景:
- 文件系统、组织结构树、UI控件树
优缺点:
- ✅ 优点:结构清晰、方便扩展
- ❌ 缺点:类型检查复杂、可能滥用层级
9. 装饰器模式(Decorator Pattern)
定义: 动态地给对象添加新的功能,而不改变其结构。
意图: 通过包装类扩展对象功能,而非继承。
PHP 示例:
<?php
interface Notifier {
public function send(string $msg): void;
}
class BasicNotifier implements Notifier {
public function send(string $msg): void {
echo "Send basic: $msg\n";
}
}
class EmailDecorator implements Notifier {
protected Notifier $notifier;
public function __construct(Notifier $notifier) {
$this->notifier = $notifier;
}
public function send(string $msg): void {
$this->notifier->send($msg);
echo "Send email: $msg\n";
}
}
// 使用
$notifier = new EmailDecorator(new BasicNotifier());
$notifier->send("Hello User");
?>应用场景:
- 动态添加日志、缓存、通知功能
- 比如 I/O 流过滤器
优缺点:
- ✅ 优点:灵活、符合开闭原则
- ❌ 缺点:过多装饰器可能使调试复杂
10. 外观模式(Facade Pattern)
定义: 为复杂系统提供一个简单的统一接口。
意图: 简化系统使用,隐藏复杂实现。
现实比喻: 比如你住酒店,只需打电话给前台,前台就会帮你联系客房服务、餐饮、洗衣、叫车等。你不需要直接与这些部门打交道。
PHP 示例:
<?php
class CPU { public function start() { echo "CPU Start\n"; } }
class Memory { public function load() { echo "Memory Load\n"; } }
class Disk { public function read() { echo "Disk Read\n"; } }
class ComputerFacade {
private CPU $cpu;
private Memory $memory;
private Disk $disk;
public function __construct() {
$this->cpu = new CPU();
$this->memory = new Memory();
$this->disk = new Disk();
}
public function startComputer(): void {
$this->cpu->start();
$this->memory->load();
$this->disk->read();
echo "Computer Started\n";
}
}
// 使用
$computer = new ComputerFacade();
$computer->startComputer();
//================================
// 示例二
// 子系统类
class TV {
public function on() { echo "电视已打开\n"; }
public function off() { echo "电视已关闭\n"; }
}
class Light {
public function on() { echo "灯光已打开\n"; }
public function off() { echo "灯光已关闭\n"; }
}
// 外观类
class HomeFacade {
private $tv;
private $light;
public function __construct() {
$this->tv = new TV();
$this->light = new Light();
}
public function movieMode() {
echo "进入观影模式:\n";
$this->light->off();
$this->tv->on();
}
public function leaveHome() {
echo "离家模式:\n";
$this->tv->off();
$this->light->off();
}
}
// 客户端调用
$facade = new HomeFacade();
$facade->movieMode();
$facade->leaveHome();
/**
* 输出
* 进入观影模式:
* 灯光已关闭
* 电视已打开
* 离家模式:
* 电视已关闭
* 灯光已关闭
*/
?>应用场景:
- 系统启动流程封装
- 子系统复杂,外部仅需统一入口
优缺点:
- ✅ 优点:简化接口、降低耦合
- ❌ 缺点:可能隐藏系统细节、不易扩展
11. 享元模式(Flyweight Pattern)
定义: 共享大量细粒度对象,减少内存使用。
核心思想: 通过共享对象,减少内存占用,提高性能。 适合用于有大量相似对象的场景。
意图: 通过共享相同状态来节省资源。
现实比喻: 游戏中同样的“树”对象可以复用,只改变坐标,而不必为每棵树创建独立实例。
PHP 示例:
<?php
class Character {
private string $symbol;
public function __construct(string $symbol) { $this->symbol = $symbol; }
public function render(int $size): void {
echo "Render '{$this->symbol}' with size $size\n";
}
}
class CharacterFactory {
private array $pool = [];
public function getCharacter(string $symbol): Character {
if (!isset($this->pool[$symbol])) {
$this->pool[$symbol] = new Character($symbol);
}
return $this->pool[$symbol];
}
}
// 使用
$factory = new CharacterFactory();
$c1 = $factory->getCharacter("A");
$c2 = $factory->getCharacter("A");
var_dump($c1 === $c2); // true
$c1->render(12);
//===========================
// 示例二
// 共享对象
class TreeType {
private $name;
private $color;
public function __construct($name, $color) {
$this->name = $name;
$this->color = $color;
}
public function draw($x, $y) {
echo "绘制树:{$this->name},颜色:{$this->color},位置:($x, $y)\n";
}
}
// 工厂类
class TreeFactory {
private static $treeTypes = [];
public static function getTreeType($name, $color) {
$key = $name . "_" . $color;
if (!isset(self::$treeTypes[$key])) {
self::$treeTypes[$key] = new TreeType($name, $color);
}
return self::$treeTypes[$key];
}
}
// 客户端代码
$tree1 = TreeFactory::getTreeType("松树", "绿色");
$tree2 = TreeFactory::getTreeType("松树", "绿色");
$tree3 = TreeFactory::getTreeType("樱花", "粉色");
$tree1->draw(10, 20);
$tree2->draw(30, 40);
$tree3->draw(50, 60);
/**
* 输出:
* 绘制树:松树,颜色:绿色,位置:(10, 20)
* 绘制树:松树,颜色:绿色,位置:(30, 40)
* 绘制树:樱花,颜色:粉色,位置:(50, 60)
*/
?>应用场景:
- 文本编辑器、地图标记对象复用
优缺点:
- ✅ 优点:节省内存、提高性能;减少对象创建的开销;
- ❌ 缺点:逻辑复杂、需区分内部外部状态
12. 代理模式(Proxy Pattern)
定义: 为其他对象提供一种代理以控制对它的访问。
现实比喻: 请律师(代理)帮你打官司,你不用直接和法院沟通。
意图: 在不改变目标对象的情况下增加额外控制。
PHP 示例:
<?php
interface Image {
public function display(): void;
}
class RealImage implements Image {
private string $filename;
public function __construct(string $filename) {
$this->filename = $filename;
$this->loadFromDisk();
}
private function loadFromDisk() {
echo "从磁盘加载图片:" . $this->filename . "\n";
}
public function display(): void {
echo "显示图片:" . $this->filename . "\n";
}
}
class ProxyImage implements Image {
private ?RealImage $realImage = null;
private string $filename;
public function __construct(string $filename) { $this->filename = $filename; }
public function display(): void {
if ($this->realImage === null) {
$this->realImage = new RealImage($this->filename);
}
$this->realImage->display();
}
}
// 使用
$image = new ProxyImage("photo.jpg");
$image->display(); // 第一次加载
$image->display(); // 第二次复用缓存
/**
* 输出:
* 从磁盘加载图片:photo.jpg
* 显示图片:photo.jpg
* 显示图片:photo.jpg
*/
?>应用场景:
- 延迟加载、权限控制、远程代理、安全代理、缓存代理、虚拟代理等
优缺点:
- ✅ 优点:控制访问、增强功能;控制对象的访问(例如懒加载、权限控制、日志记录等);提供间接层以增强对象功能。
- ❌ 缺点:增加系统复杂度
🧩 三、行为型模式(Behavioral Patterns)
13. 策略模式(Strategy Pattern)
核心思想: 定义一系列算法,把它们封装起来,使它们可以互相替换,算法的变化不会影响使用算法的对象。
现实比喻: 比如“出行策略”:可以选择公交、地铁、打车、步行等,你可以在不改出行系统的情况下自由切换。
PHP 示例:
<?php
interface TravelStrategy {
public function travel();
}
class BusStrategy implements TravelStrategy {
public function travel() {
echo "乘坐公交出行\n";
}
}
class TaxiStrategy implements TravelStrategy {
public function travel() {
echo "打车出行\n";
}
}
class WalkStrategy implements TravelStrategy {
public function travel() {
echo "步行出行\n";
}
}
class Traveler {
private $strategy;
public function setStrategy(TravelStrategy $strategy) {
$this->strategy = $strategy;
}
public function go() {
$this->strategy->travel();
}
}
// 客户端调用
$t = new Traveler();
$t->setStrategy(new BusStrategy());
$t->go();
$t->setStrategy(new TaxiStrategy());
$t->go();输出:
乘坐公交出行
打车出行优点:
- 提高代码灵活性;
- 避免冗长的 if-else;
- 新增算法不影响原有系统。
14. 观察者模式(Observer Pattern)
核心思想: 一个对象(被观察者)状态发生变化时,自动通知所有依赖它的对象(观察者)。
现实比喻: 公众号推送:用户订阅后,当有新消息发布时,系统会自动推送通知。
PHP 示例:
<?php
interface Observer {
public function update($message);
}
class User implements Observer {
private $name;
public function __construct($name) { $this->name = $name; }
public function update($message) {
echo "{$this->name} 收到消息:{$message}\n";
}
}
class WeChatAccount {
private $observers = [];
public function addObserver(Observer $observer) {
$this->observers[] = $observer;
}
public function notify($message) {
foreach ($this->observers as $observer) {
$observer->update($message);
}
}
}
// 客户端调用
$account = new WeChatAccount();
$account->addObserver(new User("小明"));
$account->addObserver(new User("小红"));
$account->notify("新文章发布啦!");输出:
小明 收到消息:新文章发布啦!
小红 收到消息:新文章发布啦!优点:
- 解耦发布者与订阅者;
- 可动态增加或移除观察者;
- 广泛用于事件系统、消息通知、Redis 订阅发布。
15. 命令模式(Command Pattern)
核心思想: 将请求封装为对象,从而可用不同请求参数化客户端、记录日志、撤销操作等。
现实比喻: 遥控器可以绑定“开灯”“关灯”等命令,用户只需按键,而不需要知道灯的实现逻辑。
PHP 示例:
<?php
interface Command {
public function execute();
}
class Light {
public function on() { echo "灯已打开\n"; }
public function off() { echo "灯已关闭\n"; }
}
class LightOnCommand implements Command {
private $light;
public function __construct(Light $light) { $this->light = $light; }
public function execute() { $this->light->on(); }
}
class LightOffCommand implements Command {
private $light;
public function __construct(Light $light) { $this->light = $light; }
public function execute() { $this->light->off(); }
}
class RemoteControl {
private $command;
public function setCommand(Command $command) { $this->command = $command; }
public function pressButton() { $this->command->execute(); }
}
// 客户端调用
$light = new Light();
$remote = new RemoteControl();
$remote->setCommand(new LightOnCommand($light));
$remote->pressButton();
$remote->setCommand(new LightOffCommand($light));
$remote->pressButton();输出:
灯已打开
灯已关闭优点:
- 命令与执行者完全解耦;
- 可轻松实现撤销、重做;
- 常用于任务队列、事务回滚、宏操作等。
16. 状态模式(State Pattern)
核心思想: 允许对象在内部状态改变时改变它的行为,看起来像是修改了类。
现实比喻: 一个订单的状态(未支付、已支付、已发货、已完成)不同,执行的操作也不同。
PHP 示例:
<?php
interface State {
public function handle();
}
class UnpaidState implements State {
public function handle() { echo "等待付款中\n"; }
}
class PaidState implements State {
public function handle() { echo "订单已支付,准备发货\n"; }
}
class ShippedState implements State {
public function handle() { echo "订单已发货\n"; }
}
class OrderContext {
private $state;
public function setState(State $state) { $this->state = $state; }
public function request() { $this->state->handle(); }
}
// 客户端调用
$order = new OrderContext();
$order->setState(new UnpaidState());
$order->request();
$order->setState(new PaidState());
$order->request();
$order->setState(new ShippedState());
$order->request();输出:
等待付款中
订单已支付,准备发货
订单已发货优点:
- 状态切换清晰;
- 消除复杂的 if-else;
- 适用于订单、流程审批、游戏状态机等系统。
17. 职责链模式(Chain of Responsibility Pattern)
定义: 将多个处理器按顺序连接起来,形成一条“处理链”,一个请求沿着链传递,直到有处理器负责处理它为止。
意图: 解耦请求发送者与接收者,让多个对象都有机会处理请求。
PHP 示例:
<?php
abstract class Handler {
protected ?Handler $next = null;
public function setNext(Handler $handler): Handler {
$this->next = $handler;
return $handler;
}
public function handle($level) {
if ($this->next) {
$this->next->handle($level);
}
}
}
class InfoHandler extends Handler {
public function handle($level) {
if ($level == 'INFO') echo "处理信息级别日志\n";
else parent::handle($level);
}
}
class ErrorHandler extends Handler {
public function handle($level) {
if ($level == 'ERROR') echo "处理错误级别日志\n";
else parent::handle($level);
}
}
class FatalHandler extends Handler {
public function handle($level) {
if ($level == 'FATAL') echo "处理严重错误日志\n";
else parent::handle($level);
}
}
// 客户端调用
$info = new InfoHandler();
$error = new ErrorHandler();
$fatal = new FatalHandler();
$info->setNext($error)->setNext($fatal);
$info->handle('ERROR');
$info->handle('FATAL');输出:
处理错误级别日志
处理严重错误日志优缺点:
- ✅ 灵活组合处理链,易扩展。
- ❌ 不易调试,请求可能被忽略。
18. 解释器模式(Interpreter Pattern)
定义: 给定一种语言,定义它的语法表示,并定义一个解释器来解释该语言中的句子。
意图: 为语言、规则、脚本或表达式建立解释引擎。
PHP 示例:
<?php
interface Expression {
public function interpret(array $context): bool;
}
class VariableExpression implements Expression {
private $name;
public function __construct($name) { $this->name = $name; }
public function interpret(array $context): bool {
return $context[$this->name] ?? false;
}
}
class AndExpression implements Expression {
private $expr1, $expr2;
public function __construct(Expression $expr1, Expression $expr2) {
$this->expr1 = $expr1; $this->expr2 = $expr2;
}
public function interpret(array $context): bool {
return $this->expr1->interpret($context) && $this->expr2->interpret($context);
}
}
class OrExpression implements Expression {
private $expr1, $expr2;
public function __construct(Expression $expr1, Expression $expr2) {
$this->expr1 = $expr1; $this->expr2 = $expr2;
}
public function interpret(array $context): bool {
return $this->expr1->interpret($context) || $this->expr2->interpret($context);
}
}
// 客户端
$a = new VariableExpression("A");
$b = new VariableExpression("B");
$expr = new OrExpression($a, $b);
$context = ["A" => true, "B" => false];
echo $expr->interpret($context) ? "真\n" : "假\n";输出:
真优缺点:
- ✅ 可实现复杂规则解析。
- ❌ 不适合大型语法系统(类会爆炸)。
19. 迭代器模式(Iterator Pattern)
定义: 提供一种顺序访问集合对象中元素的方法,而不暴露其内部结构。
意图: 统一集合遍历接口。
PHP 示例:
<?php
class BookCollection implements Iterator {
private array $books = [];
private int $position = 0;
public function addBook($book) { $this->books[] = $book; }
public function current(): mixed { return $this->books[$this->position]; }
public function next(): void { ++$this->position; }
public function key(): mixed { return $this->position; }
public function valid(): bool { return isset($this->books[$this->position]); }
public function rewind(): void { $this->position = 0; }
}
// 客户端
$collection = new BookCollection();
$collection->addBook("设计模式解析");
$collection->addBook("PHP进阶实战");
foreach ($collection as $book) {
echo "书名:$book\n";
}输出:
书名:设计模式解析
书名:PHP进阶实战优缺点:
- ✅ 封装遍历逻辑,支持多种遍历方式。
- ❌ 复杂数据结构可能需要多个迭代器类。
20. 中介者模式(Mediator Pattern)
定义: 通过一个中介对象来封装一系列对象之间的交互,使对象不必显式相互引用。
意图: 减少对象之间的耦合度。
PHP 示例:
<?php
interface Mediator {
public function notify($sender, $event);
}
class ChatRoom implements Mediator {
private array $users = [];
public function register(User $user) { $this->users[] = $user; }
public function notify($sender, $message) {
foreach ($this->users as $user) {
if ($user !== $sender) {
$user->receive($message);
}
}
}
}
class User {
private $name;
private Mediator $mediator;
public function __construct($name, Mediator $mediator) {
$this->name = $name; $this->mediator = $mediator;
}
public function send($message) {
echo "{$this->name} 发送:$message\n";
$this->mediator->notify($this, $message);
}
public function receive($message) {
echo "{$this->name} 收到:$message\n";
}
}
// 客户端
$room = new ChatRoom();
$user1 = new User("Alice", $room);
$user2 = new User("Bob", $room);
$room->register($user1);
$room->register($user2);
$user1->send("你好,Bob!");输出:
Alice 发送:你好,Bob!
Bob 收到:你好,Bob!优缺点:
- ✅ 降低耦合度,集中通信控制。
- ❌ 中介者可能过于复杂。
21. 备忘录模式(Memento Pattern)
定义: 在不破坏封装性的前提下,捕获对象的内部状态,以便在以后恢复。
意图: 支持撤销与恢复。
PHP 示例:
<?php
class EditorMemento {
public function __construct(private string $content) {}
public function getContent(): string { return $this->content; }
}
class Editor {
private string $content = '';
public function type($text) { $this->content .= $text; }
public function save(): EditorMemento { return new EditorMemento($this->content); }
public function restore(EditorMemento $memento) { $this->content = $memento->getContent(); }
public function getContent() { return $this->content; }
}
// 客户端
$editor = new Editor();
$editor->type("第一句。");
$save1 = $editor->save();
$editor->type("第二句。");
echo "当前内容:" . $editor->getContent() . "\n";
$editor->restore($save1);
echo "恢复后内容:" . $editor->getContent() . "\n";输出:
当前内容:第一句。第二句。
恢复后内容:第一句。优缺点:
- ✅ 支持撤销、版本控制。
- ❌ 占用内存较多。
22. 模板方法模式(Template Method Pattern)
定义: 定义算法框架,将一些步骤延迟到子类中实现。
意图: 在父类中定义固定流程,让子类定制特定步骤。
PHP 示例:
<?php
abstract class Game {
final public function play() {
$this->init();
$this->startPlay();
$this->endPlay();
}
abstract protected function init();
abstract protected function startPlay();
abstract protected function endPlay();
}
class Football extends Game {
protected function init() { echo "足球比赛准备中\n"; }
protected function startPlay() { echo "足球比赛开始\n"; }
protected function endPlay() { echo "足球比赛结束\n"; }
}
// 客户端
$game = new Football();
$game->play();输出:
足球比赛准备中
足球比赛开始
足球比赛结束优缺点:
- ✅ 封装流程逻辑,复用性高。
- ❌ 过多继承可能影响灵活性。
23. 访问者模式(Visitor Pattern)
定义: 表示一个作用于对象结构中各元素的操作,可在不改变类的前提下定义新的操作。
意图: 为一组对象增加新的操作,而不修改这些对象的类。
PHP 示例:
<?php
interface Visitor {
public function visitBook(Book $book);
public function visitFruit(Fruit $fruit);
}
interface ItemElement {
public function accept(Visitor $visitor);
}
class Book implements ItemElement {
public function __construct(public string $name, public float $price) {}
public function accept(Visitor $visitor) { $visitor->visitBook($this); }
}
class Fruit implements ItemElement {
public function __construct(public string $name, public float $price) {}
public function accept(Visitor $visitor) { $visitor->visitFruit($this); }
}
class PriceVisitor implements Visitor {
public function visitBook(Book $book) { echo "书籍 {$book->name} 价格:{$book->price} 元\n"; }
public function visitFruit(Fruit $fruit) { echo "水果 {$fruit->name} 价格:{$fruit->price} 元\n"; }
}
// 客户端
$items = [new Book("设计模式", 88), new Fruit("苹果", 6.5)];
$visitor = new PriceVisitor();
foreach ($items as $item) $item->accept($visitor);输出:
书籍 设计模式 价格:88 元
水果 苹果 价格:6.5 元优缺点:
- ✅ 不修改数据结构即可添加操作;
- ❌ 添加新元素类型需改所有访问者。
🔧 四、实际应用(PHP 框架中的设计模式)
| 框架 | 使用的设计模式 | 示例 |
|---|---|---|
| Laravel | 单例模式 | App::make()、DB::connection() |
| Laravel | 观察者模式 | Event::listen()、模型事件 |
| Laravel | 工厂模式 | Validator::make() |
| Symfony | 依赖注入 + 服务容器 | 结合工厂与单例 |
| Yii | 策略模式 | 缓存、行为、组件替换 |
