PHP设计模式实战应用


PHP设计模式实战应用

设计模式是面向对象编程中经过验证的解决方案,它们不是可以直接复制的代码,而是解决特定问题的模板。在PHP开发中,合理使用设计模式可以让代码更灵活、更易维护、更易扩展。本文将介绍几种在PHP项目中常用的设计模式及其实战应用。

一、单例模式

确保一个类只有一个实例,常用于数据库连接、配置管理等场景:

class Database {
    private static ?Database $instance = null;
    private PDO $pdo;

    private function __construct() {
        $this->pdo = new PDO(
            'mysql:host=localhost;dbname=myapp',
            'root', '',
            [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
        );
    }

    public static function getInstance(): self {
        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'); }
}

二、工厂模式

// 简单工厂
class NotificationFactory {
    public static function create(string $type): Notification {
        return match($type) {
            'email' => new EmailNotification(),
            'sms' => new SmsNotification(),
            'push' => new PushNotification(),
            default => throw new \InvalidArgumentException("不支持的类型: $type")
        };
    }
}

// 抽象工厂
interface StorageFactory {
    public function createConnection(): StorageConnection;
    public function createQueryBuilder(): QueryBuilder;
}

class MySQLFactory implements StorageFactory {
    public function createConnection(): StorageConnection {
        return new MySQLConnection();
    }
    public function createQueryBuilder(): QueryBuilder {
        return new MySQLQueryBuilder();
    }
}

三、策略模式

定义一系列算法,让它们可以互相替换。非常适合处理业务逻辑中的条件分支:

interface PricingStrategy {
    public function calculate(float $price): float;
}

class RegularPricing implements PricingStrategy {
    public function calculate(float $price): float { return $price; }
}

class DiscountPricing implements PricingStrategy {
    public function __construct(private float $discount) {}
    public function calculate(float $price): float {
        return $price * (1 - $this->discount);
    }
}

class VIPPricing implements PricingStrategy {
    public function calculate(float $price): float {
        return $price * 0.7; // VIP七折
    }
}

class Order {
    public function __construct(private PricingStrategy $strategy) {}
    public function getTotal(float $price): float {
        return $this->strategy->calculate($price);
    }
}

四、观察者模式

interface EventListener {
    public function handle(Event $event): void;
}

class EventDispatcher {
    private array $listeners = [];

    public function listen(string $event, EventListener $listener): void {
        $this->listeners[$event][] = $listener;
    }

    public function dispatch(Event $event): void {
        $listeners = $this->listeners[get_class($event)] ?? [];
        foreach ($listeners as $listener) {
            $listener->handle($event);
        }
    }
}

// 使用
class UserRegisteredEvent extends Event {
    public function __construct(public User $user) {}
}

$dispatcher->listen(UserRegisteredEvent::class, new SendWelcomeEmail());
$dispatcher->listen(UserRegisteredEvent::class, new CreateDefaultProfile());
$dispatcher->dispatch(new UserRegisteredEvent($user));

五、装饰器模式

interface TextFormatter {
    public function format(string $text): string;
}

class PlainText implements TextFormatter {
    public function format(string $text): string { return $text; }
}

class BoldDecorator implements TextFormatter {
    public function __construct(private TextFormatter $formatter) {}
    public function format(string $text): string {
        return '' . $this->formatter->format($text) . '';
    }
}

class ItalicDecorator implements TextFormatter {
    public function __construct(private TextFormatter $formatter) {}
    public function format(string $text): string {
        return '' . $this->formatter->format($text) . '';
    }
}

// 组合使用
$text = new ItalicDecorator(new BoldDecorator(new PlainText()));
echo $text->format('Hello'); // Hello

设计模式不是银弹,不要为了使用而使用。关键在于理解每种模式解决的问题,在合适的场景下自然地运用它们。建议从项目中常见的痛点出发,看看哪种模式能优雅地解决你的问题。


0.082661s