Hugh's Blog

PHP 设计模式

设计模式在很多语言都有用到,PHP 也不例外,下面是一些常见的 PHP 设计模式,做个记录。

工厂模式

平常我们获取实例,都是使用 new 来获取,如果在后期对类有修改,就需要改很多个地方,而工厂模式类可以把实例化对象封装成方法,后期修改只需修改工厂类就行。

// 工厂模式
class Factory
{
    public static function getDb()
    {
        $db = new Db();
        return $db;
    }
}
// 使用
$db = Factory::getDb();

单例模式

对于需要频繁创建和销毁的对象,为了节约系统资源,只创建一个实例,可以提高一定的性能,例如 MySQL, Redis 等,单例模式的作用就是确保只有一个实例被创建,避免重复构造。

但是滥用单例模式会带来一些问题,如数据库单例可能会因为连接对象过多而溢出;如单例对象长时间不使用,有可能会被系统当垃圾回收,这会导致对象状态丢失。

// 单例模式
class Db
{
    protected $conn;

    private function __construct() {}

    public static function getConnection()
    {
        if (self::$conn) {
            return self::$conn;
        } else {
            self::$conn = new self();
            return self::$conn;
        }
    }
}

// 此时工厂模式也需要更改
class Factory
{
    public static function getDb()
    {
        $db = Db::getConnection();
        return $db;
    }
}

注册树模式

注册树模式有点类似全局变量,注册实例、获取实例、删除实例。

// 注册树模式
class Register
{
    protected static $instances;

    public static function set($alias, $instance)
    {
        self::$instances[$alias] = $instance;
    }

    public static function get($alias)
    {
        if (isset(self::$instances[$alias])) {
            return self::$instances[$alias];
        } else {
            return null;
        }
    }

    public static function remove($alias)
    {
        unset(self::$instances[$alias]);
    }
}

// 更改工厂模式
class Factory
{
    public static function getDb()
    {
        $db = Db::getConnection();
        Register::set('db', $db);
    }
}

// 获取实例
$db = Register::get('db');

适配器模式

适配器模式的作用是用于将不同实例的接口适配成一个同一的接口,方便调用,例如将 PDO 数据库封装、新的 API 接口与旧的 API 接口兼容等等。

// 目标角色
interface Target
{
    public function func1();
    public function func2();
}
// 源角色
class Adaptee
{  
    public function func1()
    { 
        echo 'func1';
    }  
}
// 类适配器角色
class Adapter implements Target
{
    private $adaptee;

    function __construct(Adaptee $adaptee)
    {
        $this->adaptee = $adaptee;   
    }

    // 调用源角色 func1 方法
    public function func1()
    {
        $this->adaptee->func1();  
    }

    // 目标角色新增方法
    public function func2(){  
        echo 'func2';     
    }
}

// 使用
$adaptee = new Adaptee();
$adapter = new Adapter($adaptee);
$adapter->func1();
$adapter->func2();

观察者模式

观察者模式是指一个实例通过添加一个方法(即注册观察者),当该实例有更改时,会将消息发送到已注册的观察者实例上,由观察者做后续操作,这两个过程耦合程度很低。

// 观察者接口
interface Observer
{
    public function watch();
}
// 比如一篇文章
interface Subject
{
    public function register(Observer $observer);
    public function notify();
}
// 主题
class Action implements Subject
{
    private $_observers = [];

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

    public function notify()
    {
        foreach ($this->_observers as $observer) {
            $observer->watch();
        }
    }
}

// 观察者
class People implements Observer
{
    public function watch()
    {
        echo 'People watching.';
    }
}

// 应用实例
$action = new Action();
$action->register(new People());
$action->notify();

参考

大话 PHP 设计模式

设计模式