首页 / PHP 入门教程 / PHP 设计模式简介

PHP 入门教程

PHP 设计模式简介

本教程共 65 篇 · 第 61 篇 · 更新于 2026-07-24 · 约 10 分钟阅读

PHPPHP8设计模式单例模式工厂模式观察者模式策略模式

61. PHP 设计模式简介

本节目标:了解常用设计模式的核心思想,能够在合适场景下选择并应用正确的模式。

设计模式是解决常见软件设计问题的经过验证的方案。它不是具体的代码,而是一种思想。掌握设计模式能让代码更易维护、更易扩展。


1. 单例模式(Singleton)

确保一个类只有一个实例,并提供一个全局访问点。常用于数据库连接、配置管理等场景。

<?php
class Database
{
    private static ?self $instance = null;

    private PDO $pdo;

    private function __construct()
    {
        $this->pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '123456');
    }

    public static function getInstance(): self
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function getPdo(): PDO
    {
        return $this->pdo;
    }

    // 禁止克隆和反序列化
    private function __clone() {}
    public function __wakeup()
    {
        throw new Exception("Cannot unserialize singleton");
    }
}

// 使用
$db = Database::getInstance();
$stmt = $db->getPdo()->query("SELECT * FROM users");
Note

单例模式有其争议。全局状态会让测试变得困难,依赖注入容器(如 Laravel 的服务容器)是更好的替代方案。仅在确有必要时使用单例。


2. 工厂模式(Factory)

将对象的创建逻辑封装到工厂类中,调用者无需关心具体实例化过程。

<?php
interface Logger {
    public function log(string $message): void;
}

class FileLogger implements Logger {
    public function log(string $message): void {
        file_put_contents('app.log', $message . PHP_EOL, FILE_APPEND);
    }
}

class DbLogger implements Logger {
    public function log(string $message): void {
        echo "[DB] {$message}\n";
    }
}

class LoggerFactory {
    public static function create(string $type): Logger {
        return match ($type) {
            'file' => new FileLogger(),
            'db'   => new DbLogger(),
            default => throw new InvalidArgumentException('未知日志类型'),
        };
    }
}

// 使用
$logger = LoggerFactory::create('file');
$logger->log('系统启动');
Tip

工厂模式让代码更易扩展。新增日志类型时,只需修改工厂,不影响调用方。


3. 观察者模式(Observer)

定义对象间的一对多依赖,当一个对象状态改变时,所有依赖者自动收到通知。

<?php
interface Observer {
    public function update(string $event): void;
}

class UserService {
    private array $observers = [];

    public function attach(Observer $observer): void {
        $this->observers[] = $observer;
    }

    public function createUser(string $name): void {
        echo "创建用户:{$name}\n";
        $this->notify('user.created');
    }

    private function notify(string $event): void {
        foreach ($this->observers as $observer) {
            $observer->update($event);
        }
    }
}

class EmailNotifier implements Observer {
    public function update(string $event): void {
        if ($event === 'user.created') {
            echo "发送欢迎邮件\n";
        }
    }
}

class LogNotifier implements Observer {
    public function update(string $event): void {
        echo "记录日志:{$event}\n";
    }
}

// 使用
$service = new UserService();
$service->attach(new EmailNotifier());
$service->attach(new LogNotifier());
$service->createUser('张三');

4. 策略模式(Strategy)

定义一系列算法,将它们封装起来,并且使它们可以互相替换。

<?php
interface PaymentStrategy {
    public function pay(float $amount): string;
}

class AlipayStrategy implements PaymentStrategy {
    public function pay(float $amount): string {
        return "支付宝支付 {$amount} 元";
    }
}

class WechatStrategy implements PaymentStrategy {
    public function pay(float $amount): string {
        return "微信支付 {$amount} 元";
    }
}

class PaymentContext {
    public function __construct(private PaymentStrategy $strategy) {}

    public function executePay(float $amount): string {
        return $this->strategy->pay($amount);
    }

    public function setStrategy(PaymentStrategy $strategy): void {
        $this->strategy = $strategy;
    }
}

// 使用
$payment = new PaymentContext(new AlipayStrategy());
echo $payment->executePay(100); // 支付宝支付 100 元

$payment->setStrategy(new WechatStrategy());
echo $payment->executePay(100); // 微信支付 100 元

5. 模式使用建议

场景推荐模式
全局唯一的数据库连接单例模式
根据不同条件创建不同对象工厂模式
事件触发后执行多个动作观察者模式
多种算法/策略可互换策略模式
Note

不要为了用模式而用模式。简单的逻辑直接写即可,过度设计会增加复杂度。


小结

设计模式是前人总结的最佳实践。理解核心思想后,结合具体业务灵活运用,能让代码结构更清晰、更易于维护。


来源:参考了 php-the-right-way「Design Patterns」、refactoring.guru,改写后所得。