PHP设计模式

MyAnswer博客


PHP常用六大设计模式: 单例模式,工厂模式,注册模式,适配器模式,观察者模式,策略模式;


一.单例模式理解:

  1. 使用某个类的对象只被创建一次

  2. 单例模式最大的好处就是减少资源的浪费,保证整个环境中只存在一个实例对象,特别适用于资源连接的编写

  3. 单例模式的意思就是创建一个资源(对象,数据库连接),本质就是防止外部实例化类+判断是否存在返回,或创建后返回

<?php

//单例模式(三私一公)
class Single
{
    //私有的构造方法,方式被实例化
    private function __construct()
    {
    
    }
    //私有的克隆方法,防止被克隆
    private function __clone()
    {

    }
    //私有化列表实例对象
    private static $instance = null;
    //公有静态实例方法
    public function getInstance()
    {
        //判断实例是否为空,如果为空则创建实例
        if (self::$instance == null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
}


二.工厂模式理解:

    1.工厂方法或者类生成对象,而不是在代码中直接new

    2.我们定义一个专门用来创建其它对象的类,这样在需要调用某个类的时候,我们就不需要去使用new关键字实例化这个类,而是通过我们的工厂类调用某个方法得到类的实例

    3.好处:当我们对象所对应的类名发生变化的时候,我们只需要改一下工厂类类里面的实例化方法即可,不需要外部改所有的地方

<?php

//工厂模式
class Factory
{
    //创建数据库对象
    static function createDatabase()
    {
        $db = new Database();
        return $db;
    }
}
$db = Factory::createDatabase();


三.注册器模式理解:

   1.全局共享和交换对象

   2.单纯使用工厂模式还是要不断的创建对象,结合注册树模式,就简化了创建对象的麻烦

<?php

//注册模式
class Register
{
    //保存所有实例化对象
    protected static $objects;

    //注册对象
    public static function set($alias, $object)
    {
        self::$objects[$alias] = $object;
    }

    //获取对象
    public static function get($alias)
    {
        return self::$objects[$alias];
    }

    //删除对象
    public static function _unset($alias)
    {
        unset(self::$objects[$alias]);

    }

}

//普通使用
class a
{

}

//注册
Register::set('a', new a());
//获取
Register::get('a');
//删除
Register::_unset('a');

//在工厂模式下使用
class Factory
{
    //创建数据库对象
    static function createDatabase()
    {
        $db = new Database();
        //对象注入
        Register::set('db', $db);
        return $db;
    }
}

//工厂模式创建放回
$db = Factory::createDatabase();
//注册树获取
$db1 = Register::get('db');

四.适配器模式理解:

1.使用适配器策略是为了更好的兼容,类似手机电源适配器,如果能用一个充电器对所有手机充电当然是最方便的,无论什么手机,都只需要拿一个充电器,否则,不同手机不同充电器太麻烦了

2.新建一个接口,然后在这个接口里面声明统一的方法体,再让不同的类去实现这个接口,和重写其抽象方法,当我们在入口文件使用到不同的类的时候,就是实例化的类名不同,其它调用方法体的地方都一致

应用场景

如程序数据库有关联mysql,mysqli,pdo,sqlite 等操作,而你需要根据情况切换数据库操作时,可以使用适配器模式统一接口,这样代码中除了数据库配置之外,就不需要做额外的改动

<?php

//接口统一约束
interface IDatabase
{
    //连接数据库
    public function connect($host, $username, $password, $database)
    {

    }

    //查询数据
    public function query($sql)
    {

    }

    //关闭连接
    public function close()
    {

    }

}

//Mysql的适配器
class Mysql implements IDatabase
{

    protected $connent; //连接资源

    /** 实现连接
     * @param $host 地址
     * @param $username 用户名
     * @param $password 密码
     * @param $database 数据库
     */
    public function connect($host, $username, $password, $database)
    {
        $connect = mysql_connect($host, $username, $password);
        mysql_select_db($database, $connect);
        $this->connent = $connect;
    }

    /**
     * 实现查询
     * @param $sql 需要查询的sql
     * @return resource
     */
    public function query($sql)
    {
        return mysql_query($sql);
    }

    /**
     * 关闭连接
     */
    public function close()
    {
        mysql_close();
    }
}

//Mysql的适配器
class Mysqli implements IDatabase
{

    protected $connect; //连接资源

    /** 实现连接
     * @param $host 地址
     * @param $username 用户名
     * @param $password 密码
     * @param $database 数据库
     */
    public function connect($host, $username, $password, $database)
    {
        $connect = mysqli_connect($host, $username, $password);
        mysqli_select_db($database, $connect);
        $this->connect = $connect;
    }

    /**实现查询
     * @param $sql 查询的sql
     * @return bool|mysqli_result
     */
    public function query($sql)
    {
        return mysqli_query($this->connect, $sql);
    }

    /**
     * 关闭连接
     */
    public function close()
    {
        mysqli_close($this->connect);
    }
}

//客户端使用
$host = 'localhost';
$username = 'root';
$password = 'root';
$database = 'mysql';
//mysql适配
$client = new mysql();
$client->connect($host, $username, $password, $database);
$client->query('select * from user');
$client->close();

//mysqli适配
$client = new mysqli();
$client->connect($host, $username, $password, $database);
$client->query('select * from admin');
$client->close();

五.观察者模式理解:

  1. 当一个对象状态发生变化时,依赖它的对象全部会收到通知,并且自动更新,观察者模式实现了低耦合,非侵入式的通知与更新机制

  2. 应用场景:一个事件发生后,要执行一连串更新操作,传统编程的方式,就是在事件的代码之后直接加入处理的逻辑,当更新的逻辑增多之后,代码会变得难以维护,这种方式是耦合的,侵入式的,增加新的逻辑需要修改事件的主体代码

<?php

//主体接口
interface Subject
{
    public function register(Observer $observer);

    public function notify();
}

//观察者接口
interface Observer
{
    public function watch();
}

class action implements Subject
{
    public $_observers = [];

    //注册对象
    public function register(Observer $observer)
    {
        $this->_observers[] = $observer;
    }

    //通知更新
    public function notify()
    {
        foreach ($this->_observers as $observer) {
            $observer->watch();
        }
    }


}


//观察者

class cat1 implements Observer
{

    public function watch()
    {
        echo "Dog1 watches TV" . PHP_EOL;
    }

}

class cat2 implements Observer
{

    public function watch()
    {
        echo "Dog2 watches TV" . PHP_EOL;
    }

}

class cat3 implements Observer
{

    public function watch()
    {
        echo "Dog3 watches TV" . PHP_EOL;
    }

}

$action = new action();
//注册对象
$action->register(new  cat1());
$action->register(new  cat2());
$action->register(new  cat3());

//统一通知
$action->notify();

六.策略模式理解:

  1. 定义一系列算法,将每一个算法封装起来,并让他们可以互相转换,策略模式让算法独立于使用它的客户而变化

<?php
//策略模式
abstract class Strategy{

    abstract function goSchool();

}

class Run extends Strategy{
    public function goSchool()
    {
        // TODO: Implement goSchool() method.
    }
}

class Subway extends Strategy{

    public function goSchool()
    {
      echo '来了';
    }
}
class Bike extends Strategy{

    public function goSchool()
    {
        // TODO: Implement goSchool() method.
    }
}
class Context
{
    protected $_stratege;//存储传过来的策略对象
    public function goSchoole($avil_stratery)
    {
        $this->_stratege = $avil_stratery;
        $this->_stratege->goSchool();
    }
}

$con = new Context();
$avil_stratery = new Subway();
$con->goSchoole($avil_stratery);


MyAnswer博客
请先登录后发表评论
  • 最新评论
  • 总共0条评论