本文目录导读:

在PHP项目开发中,设计模式的应用可以显著提升代码的可维护性、可扩展性和可读性,对于大多数PHP项目(特别是基于Laravel、Symfony等现代框架),以下是一些最常用且最实用的设计模式及其具体应用场景。
创建型模式
工厂方法模式
-
适用场景:
- 当需要根据输入动态创建对象,但不想暴露实例化逻辑时。
- 处理多种支付方式、文件导入/导出格式、日志驱动等。
-
PHP示例:
interface PaymentGateway { public function charge(float $amount): bool; } class StripeGateway implements PaymentGateway { public function charge(float $amount): bool { echo "通过Stripe支付: {$amount}"; return true; } } class PayPalGateway implements PaymentGateway { public function charge(float $amount): bool { echo "通过PayPal支付: {$amount}"; return true; } } // 工厂类 class PaymentFactory { public static function create(string $type): PaymentGateway { return match($type) { 'stripe' => new StripeGateway(), 'paypal' => new PayPalGateway(), default => throw new \InvalidArgumentException("Unknown payment type: {$type}"), }; } } // 使用 $gateway = PaymentFactory::create('stripe'); $gateway->charge(100);
单例模式
-
适用场景:
数据库连接器、配置管理器、日志记录器(确保全局只有一个实例)。
-
注意:在框架中(如Laravel的DI容器)通常用依赖注入替代,但原生项目中仍常用。
-
PHP示例:
class DatabaseConnection { private static ?DatabaseConnection $instance = null; private PDO $pdo; private function __construct() { // 私有的构造函数,阻止外部实例化 $this->pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass'); } public static function getInstance(): DatabaseConnection { if (self::$instance === null) { self::$instance = new self(); } return self::$instance; } public function getConnection(): PDO { return $this->pdo; } // 防止克隆和反序列化 private function __clone() {} public function __wakeup() { throw new \Exception("Cannot unserialize singleton"); } } // 使用 $db = DatabaseConnection::getInstance();
结构型模式
适配器模式
-
适用场景:
- 当需要整合第三方库或遗留代码,但其接口与当前系统不兼容时。
- 统一短信服务商API(Twilio、阿里云、AWS SNS)。
-
PHP示例:
// 第三方库的类,无法修改 class TwilioSMS { public function sendSms(string $to, string $message): string { return "Twilio发送到 {$to}: {$message}"; } } // 项目中的统一接口 interface NotificationAdapter { public function send(string $recipient, string $subject): bool; } // 适配器 class TwilioAdapter implements NotificationAdapter { private TwilioSMS $twilio; public function __construct(TwilioSMS $twilio) { $this->twilio = $twilio; } public function send(string $recipient, string $subject): bool { // 适配接口,将subject映射为message发送 $result = $this->twilio->sendSms($recipient, $subject); return str_contains($result, '发送到'); } }
策略模式
-
适用场景:
- 一个行为在运行时有多种算法实现(如订单价格计算、物流运费、促销活动)。
- 避免大量的
if-else或switch-case。
-
PHP示例:
// 策略接口 interface ShippingStrategy { public function calculate(float $weight, string $destination): float; } // 具体策略 class FedExStrategy implements ShippingStrategy { public function calculate(float $weight, string $destination): float { return $weight * 2.5 + 10; // 简单计算 } } class UPSStrategy implements ShippingStrategy { public function calculate(float $weight, string $destination): float { return $weight * 3.0 + 15; } } // 上下文类 class OrderContext { private ShippingStrategy $strategy; public function __construct(ShippingStrategy $strategy) { $this->strategy = $strategy; } public function setStrategy(ShippingStrategy $strategy): void { $this->strategy = $strategy; } public function getShippingCost(float $weight, string $destination): float { return $this->strategy->calculate($weight, $destination); } }
行为型模式
观察者模式
-
适用场景:
- 事件驱动系统,如用户注册后发送邮件、短信、记录日志。
- 框架的Event系统(Laravel的
Event和Listener本质是基于此模式)。
-
PHP示例:
// 主题(被观察者) class User { private string $name; private array $observers = []; // 观察者列表 public function attach(\SplObserver $observer): void { $this->observers[] = $observer; } public function detach(\SplObserver $observer): void { // 移除观察者逻辑(简化示例) } public function setName(string $name): void { $this->name = $name; $this->notify(); } public function getName(): string { return $this->name; } private function notify(): void { foreach ($this->observers as $observer) { $observer->update($this); // SplSubject 会调用此方法 } } } // 观察者1:发送邮件 class EmailNotifier implements \SplObserver { public function update(\SplSubject $subject): void { if ($subject instanceof User) { echo "发送注册邮件给: " . $subject->getName() . "\n"; } } } // 观察者2:记录日志 class LogHandler implements \SplObserver { public function update(\SplSubject $subject): void { if ($subject instanceof User) { echo "记录日志: 用户 {$subject->getName()} 注册\n"; } } }
模板方法模式
-
适用场景:
- 当多个类有相同的算法骨架,但某些步骤需要子类差异化实现。
- 数据入库流程(验证、格式化、保存、记录日志);单元测试的
setUp()方法。
-
PHP示例:
abstract class DataImporter { // 模板方法,定义算法骨架,`final`防止子类修改 final public function import(string $filePath): bool { $this->validate($filePath); $data = $this->parse($filePath); $this->store($data); $this->log(); return true; } protected abstract function parse(string $filePath): array; protected abstract function store(array $data): void; private function validate(string $filePath): void { if (!file_exists($filePath)) { throw new \RuntimeException("文件不存在"); } echo "验证通过...\n"; } private function log(): void { echo "导入完成, 记录日志...\n"; } } class CsvImporter extends DataImporter { protected function parse(string $filePath): array { echo "解析CSV...\n"; return [['row1'], ['row2']]; } protected function store(array $data): void { echo "存储CSV数据到数据库...\n"; } } class JsonImporter extends DataImporter { protected function parse(string $filePath): array { echo "解析JSON...\n"; return json_decode(file_get_contents($filePath), true); } protected function store(array $data): void { echo "存储JSON数据到数据库...\n"; } }
经典模式在PHP框架中的应用
- Laravel:
- 服务容器:结合了依赖注入和服务定位器。
- 门面:是代理模式的变体。
- Eloquent ORM:大量使用活动记录模式(Active Record)。
- Symfony:
- 事件分发器:经典的观察者模式。
- 依赖注入:是工厂模式的高级实现。
- 设计模式推荐程度对比:
| 模式 | 推荐度 | 核心价值 |
|---|---|---|
| 策略模式 | ⭐⭐⭐⭐⭐ | 消除条件分支 |
| 工厂模式 | ⭐⭐⭐⭐⭐ | 解耦对象创建 |
| 观察者模式 | ⭐⭐⭐⭐ | 事件驱动解耦 |
| 适配器模式 | ⭐⭐⭐⭐ | 集成第三方 |
| 单例模式 | ⭐⭐⭐ | 资源管理(慎用,易引入耦合) |
| 模板方法模式 | ⭐⭐⭐ | 复用算法骨架 |
最佳实践建议
- 不要为了模式而使用模式:如果简单的函数或类就能解决问题,不要强行套用设计模式。
- 优先依赖注入:在现代PHP框架中,依赖注入通常比纯粹的工厂类更优雅。
- 组合优于继承:多使用策略模式、观察者模式等基于组合的模式。
- 关注SOLID原则:设计模式是SOLID的具体实现形式。
对于PHP项目尤其是Web开发,策略模式(处理算法变化)、工厂方法模式(对象创建)、适配器模式(集成外部服务)和观察者模式(事件处理)是最实用、最值得优先掌握的模式。