PHP 常用设计模式

PHP 常用设计模式

设计模式是写好代码的经验总结,常用的几种要掌握。

1. 单例模式

整个项目只有一个实例,比如数据库连接。

class Db
{
    private static $instance = null;

    private function __construct() {}

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

$db = Db::getInstance();

2. 工厂模式

根据参数创建不同的对象。

class Factory
{
    public static function make($type)
    {
        $class = ucfirst($type);
        return new $class();
    }
}

$user = Factory::make('user');
$order = Factory::make('order');

3. 观察者模式

一个对象状态变化,通知所有观察者。

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

class Event
{
    private $observers = [];

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

    public function trigger($event)
    {
        foreach ($this->observers as $ob) {
            $ob->update($event);
        }
    }
}

4. 常用场景

  • 单例: 数据库、日志、配置
  • 工厂: 创建不同类的对象
  • 观察者: 事件触发、消息通知
  • 策略: 不同支付方式
  • 适配器: 兼容不同接口

5. 设计原则

  • 单一职责:一个类只做一件事
  • 开闭原则:对扩展开放,对修改关闭
  • 依赖倒置:依赖抽象不依赖具体

总结

PHP 常用设计模式要点:

  • 单例模式:只创建一个实例
  • 工厂模式:统一创建对象
  • 观察者:事件通知
  • 理解设计原则
  • 不要为了模式而模式

设计模式是工具,解决问题才是目的。


emer 发布于  2026-10-8 07:24 

PHP 常用设计模式

PHP 常用设计模式

设计模式不是玄学,是前人踩坑总结出来的套路。这篇讲 PHP 开发中最常用的几个。

1. 单例模式(最常用)

保证一个类只有一个实例,节省资源。

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

    // 构造函数私有化,禁止外部 new
    private function __construct()
    {
        $this->pdo = new PDO('mysql:host=127.0.0.1;dbname=blog', 'root', '123456');
    }

    // 禁止克隆
    private function __clone() {}

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

    public function query($sql)
    {
        return $this->pdo->query($sql);
    }
}

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

适用场景: 数据库连接、日志类、配置类。

2. 工厂模式

根据参数创建不同对象,不用直接 new。

interface Logger
{
    public function write($message);
}

class FileLogger implements Logger
{
    public function write($message)
    {
        file_put_contents('log.txt', $message . "\n", FILE_APPEND);
    }
}

class DatabaseLogger implements Logger
{
    public function write($message)
    {
        // 写入数据库
    }
}

class LoggerFactory
{
    public static function create($type)
    {
        switch ($type) {
            case 'file':
                return new FileLogger();
            case 'database':
                return new DatabaseLogger();
            default:
                throw new Exception("不支持的日志类型");
        }
    }
}

// 使用
$logger = LoggerFactory::create('file');
$logger->write("这是一条日志");

3. 观察者模式

对象状态变化时自动通知依赖它的对象。

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

class Order
{
    private $observers = [];

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

    public function pay()
    {
        // 支付逻辑
        echo "订单支付成功\n";

        // 通知所有观察者
        foreach ($this->observers as $observer) {
            $observer->update('pay_success');
        }
    }
}

class SendSmsObserver implements Observer
{
    public function update($event)
    {
        if ($event == 'pay_success') {
            echo "发送支付成功短信\n";
        }
    }
}

class SendEmailObserver implements Observer
{
    public function update($event)
    {
        if ($event == 'pay_success') {
            echo "发送支付成功邮件\n";
        }
    }
}

// 使用
$order = new Order();
$order->addObserver(new SendSmsObserver());
$order->addObserver(new SendEmailObserver());
$order->pay();

适用场景: 事件系统、消息通知。

4. 策略模式

定义一系列算法,让它们可以互相替换。

interface PayStrategy
{
    public function pay($amount);
}

class AlipayStrategy implements PayStrategy
{
    public function pay($amount)
    {
        echo "支付宝支付 {$amount} 元\n";
    }
}

class WechatPayStrategy implements PayStrategy
{
    public function pay($amount)
    {
        echo "微信支付 {$amount} 元\n";
    }
}

class OrderPay
{
    private $strategy;

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

    public function pay($amount)
    {
        $this->strategy->pay($amount);
    }
}

// 使用
$orderPay = new OrderPay();
$orderPay->setStrategy(new AlipayStrategy());
$orderPay->pay(100);

总结

常用设计模式就这几个:

  • 单例模式: 全局唯一对象(数据库连接)
  • 工厂模式: 统一创建对象
  • 观察者模式: 事件通知
  • 策略模式: 算法切换

设计模式不是为了用而用,是解决特定问题的。项目小就别硬套,过度设计比没有设计更糟。


emer 发布于  2026-10-7 07:11 

PHP 设计模式:单例、工厂、观察者实战详解

前言

设计模式不是八股文,它是前人踩坑踩出来的最佳实践。PHP 开发中最常用的三个设计模式:单例、工厂、观察者。本文用最直白的方式讲清楚。

一、单例模式(Singleton)

什么时候用

全局只需要一个实例的对象,比如:

  • 数据库连接
  • 配置管理
  • 日志对象

代码实现

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

    // 构造函数私有化,防止外部 new
    private function __construct()
    {
        $this->conn = mysqli_connect('localhost', 'user', 'pass', 'db');
    }

    // 禁止克隆
    private function __clone() {}

    // 禁止反序列化
    public function __wakeup()
    {
        throw new Exception("不能反序列化单例");
    }

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

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

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

为什么要私有化构造函数

如果构造函数是 public 的,外面就能 new Database(),那就不是单例了。

二、工厂模式(Factory)

什么时候用

需要根据不同条件创建不同对象的时候,比如:

  • 根据支付类型创建不同的支付对象(微信、支付宝、银行卡)
  • 根据数据库类型创建不同的数据库对象(MySQL、Redis)

简单工厂

<?php
interface Payment
{
    public function pay($amount);
}

class WechatPay implements Payment
{
    public function pay($amount)
    {
        echo "微信支付 {$amount} 元";
    }
}

class Alipay implements Payment
{
    public function pay($amount)
    {
        echo "支付宝支付 {$amount} 元";
    }
}

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

// 使用
$pay = PaymentFactory::make('wechat');
$pay->pay(100);

工厂模式的好处

  1. 解耦:客户端不需要知道具体怎么创建对象
  2. 易扩展:新增支付方式只需要加一个类和工厂里的一个 case
  3. 统一管理:所有对象的创建都在工厂里,方便维护

三、观察者模式(Observer)

什么时候用

一个对象状态改变时,需要通知多个其他对象,比如:

  • 用户注册后:发邮件、发短信、送积分
  • 订单状态变更后:通知仓库、通知物流、通知客服

代码实现

<?php
// 事件接口
interface Observer
{
    public function update($eventData);
}

// 事件主体
class Event
{
    private $observers = [];

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

    public function trigger($eventData)
    {
        foreach ($this->observers as $observer) {
            $observer->update($eventData);
        }
    }
}

// 具体观察者
class SendEmail implements Observer
{
    public function update($eventData)
    {
        echo "发送邮件给 {$eventData['email']}\n";
    }
}

class SendSms implements Observer
{
    public function update($eventData)
    {
        echo "发送短信给 {$eventData['phone']}\n";
    }
}

class GivePoints implements Observer
{
    public function update($eventData)
    {
        echo "给用户送 100 积分\n";
    }
}

// 使用
$event = new Event();
$event->attach(new SendEmail());
$event->attach(new SendSms());
$event->attach(new GivePoints());

// 用户注册,触发事件
$event->trigger([
    'email' => 'user@example.com',
    'phone' => '13800138000'
]);

观察者模式的好处

  1. 解耦:事件主体不需要知道谁在监听
  2. 易扩展:新增监听者只需要加一个类,不需要改原来的代码
  3. 符合开闭原则:对扩展开放,对修改关闭

四、什么时候用什么模式

场景 用什么模式
全局只需要一个实例 单例
根据条件创建不同对象 工厂
一个动作触发多个后续操作 观察者

五、常见坑

  1. 单例用太多:单例用多了会变成全局变量,代码难维护
  2. 工厂过度设计:简单逻辑就别硬上工厂,会增加复杂度
  3. 观察者滥用:所有操作都做成观察者,调试会很痛苦

总结

设计模式是工具,不是目的。

  • 单例:保证全局只有一个实例
  • 工厂:统一管理对象创建
  • 观察者:一个事件,多个响应

用对了让代码更清晰,用错了让代码更复杂。记住:先解决问题,再考虑模式。


emer 发布于  2026-10-4 10:08 
'); })();