Skip to content

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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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
<?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策略模式缓存、行为、组件替换

学而不思则罔,思而不学则殆。