Skip to content

常用设计模式

设计模式是解决特定问题的最佳实践,本文介绍 PHP 中常用的设计模式。

单例模式(Singleton)

确保一个类只有一个实例:

php
class Database {
    private static $instance = null;
    private $connection;

    private function __construct() {
        $this->connection = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
    }

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

    public function getConnection() {
        return $this->connection;
    }

    // 防止克隆和反序列化
    private function __clone() {}
    private function __wakeup() {}
}

// 使用
$db = Database::getInstance()->getConnection();

工厂模式(Factory)

创建对象而不暴露创建逻辑:

php
interface PaymentInterface {
    public function pay($amount);
}

class Alipay implements PaymentInterface {
    public function pay($amount) {
        echo "支付宝支付: ¥$amount";
    }
}

class WechatPay implements PaymentInterface {
    public function pay($amount) {
        echo "微信支付: ¥$amount";
    }
}

class PaymentFactory {
    public static function create($type) {
        switch ($type) {
            case 'alipay': return new Alipay();
            case 'wechat': return new WechatPay();
            default: throw new Exception('不支持的方式');
        }
    }
}

// 使用
$payment = PaymentFactory::create('alipay');
$payment->pay(100);

观察者模式(Observer)

事件订阅通知机制:

php
interface Observer {
    public function update($event, $data);
}

class EventDispatcher {
    private $observers = [];

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

    public function detach($event, Observer $observer) {
        if (isset($this->observers[$event])) {
            $key = array_search($observer, $this->observers[$event]);
            if ($key !== false) {
                unset($this->observers[$event][$key]);
            }
        }
    }

    public function notify($event, $data = null) {
        if (isset($this->observers[$event])) {
            foreach ($this->observers[$event] as $observer) {
                $observer->update($event, $data);
            }
        }
    }
}

// 具体观察者
class EmailNotifier implements Observer {
    public function update($event, $data) {
        echo "发送邮件通知: $event\n";
    }
}

class SmsNotifier implements Observer {
    public function update($event, $data) {
        echo "发送短信通知: $event\n";
    }
}

// 使用
$dispatcher = new EventDispatcher();
$dispatcher->attach('user.register', new EmailNotifier());
$dispatcher->attach('user.register', new SmsNotifier());
$dispatcher->notify('user.register', ['user_id' => 1]);

策略模式(Strategy)

定义算法族,让它们可以互相替换:

php
interface SortStrategy {
    public function sort(array $data): array;
}

class BubbleSort implements SortStrategy {
    public function sort(array $data): array {
        // 冒泡排序实现
        return $data;
    }
}

class QuickSort implements SortStrategy {
    public function sort(array $data): array {
        // 快速排序实现
        return $data;
    }
}

class Sorter {
    private $strategy;

    public function setStrategy(SortStrategy $strategy) {
        $this->strategy = $strategy;
    }

    public function sort(array $data): array {
        return $this->strategy->sort($data);
    }
}

// 使用
$sorter = new Sorter();
$sorter->setStrategy(new QuickSort());
$sorted = $sorter->sort([3, 1, 4, 1, 5]);

装饰器模式(Decorator)

动态添加功能:

php
interface Coffee {
    public function cost(): float;
    public function description(): string;
}

class SimpleCoffee implements Coffee {
    public function cost(): float { return 10; }
    public function description(): string { return '简单咖啡'; }
}

abstract class CoffeeDecorator implements Coffee {
    protected $coffee;
    public function __construct(Coffee $coffee) {
        $this->coffee = $coffee;
    }
}

class Milk extends CoffeeDecorator {
    public function cost(): float {
        return $this->coffee->cost() + 2;
    }
    public function description(): string {
        return $this->coffee->description() . ', 牛奶';
    }
}

class Sugar extends CoffeeDecorator {
    public function cost(): float {
        return $this->coffee->cost() + 1;
    }
    public function description(): string {
        return $this->coffee->description() . ', 糖';
    }
}

// 使用
$coffee = new SimpleCoffee();
$coffee = new Milk($coffee);
$coffee = new Sugar($coffee);
echo $coffee->description() . ' = ¥' . $coffee->cost();

注意事项

  1. 不要过度设计,简单问题用简单方案
  2. 设计模式是工具,不是教条
  3. 理解模式的意图比记住实现更重要

Binstork