PHP:设计模式之单例模式及数据库案例

设计模式的定义

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性...

简而言之,就是前人总结的,大佬认可的,约定俗成的模式。好比“驼峰法”命名,你当然可以无视之(某些严格的框架除外),但如果遵循它,可以让你的开发工作更方便更高效。

设计模式有哪些

单例模式、工厂模式、注册树模式、策略模式、适配器模式、观察者模式......据我观察,互联网上有许多不同的提法。既然是前人总结的,而不是手册里规定的,大家各有各的说法,也能够理解。

(我在2022-10-14构建的PHP官方手册里没有搜索到“模式”和“单例”相关的词条。)

单例模式的目的

单例模式是指在内存中有且只会创建一次对象的设计模式,在程序中多次使用同一个对象且作用相同的时候,为了防止频繁的创建对象,单例模式可以让程序在内存中创建一个对象,让所有的调用者都共享这一单例对象。

比如:数据库连接设计,如果每次数据库操作就new一个新连接,性能开销成倍增加,反而可能连接过多导致服务器阻塞,降低了效率。

单例模式要点:三私一公

一私:私有的静态的保存对象的属性。

静态属性的特点是全局只有一个值(引用传递),一改则全改,能够保证对象属性的唯一性。

私有权限使对象属性不被类外调用,保证安全性。

二私:私有的构造方法(__construct)

我们知道,“构造方法的权限修饰符只能是public,否则无法创建对象”。因此,我们将其设为private,即可完全阻止类外部new对象。

三私:私有的克隆方法(__clone)

我们知道,创建对象有两种方式,new和clone,因此把克隆方法也设为private,类外就无法克隆对象,阻止了创建对象的可能。

一公:公共的静态的创建对象的方法

创建对象的方法必须公共权限,否则外部无法调用,连唯一的对象都无法创建,这个类就失去了意义。

单例模式案例之数据库连接

我们就在之前连接数据库的案例上加以修改,代码如下:

class Db
{
    //私有的保存对象信息的静态属性
    private static $obj = null;

    //私有的数据库连接信息
    private $Db_host;
    private $Db_user;
    private $Db_pswd;
    private $Db_name;
    private $link;

    //私有的构造方法
    private function __construct($config = array())
    {
        $this->Db_host = $config["Db_host"];
        $this->Db_user = $config["Db_user"];
        $this->Db_pswd = $config["Db_pswd"];
        $this->Db_name = $config["Db_name"];
        $this->connectDb();
        $this->selectDb();
    }

    //私有的成员方法1
    private function connectDb()
    {
        if (!$this->link = mysqli_connect($this->Db_host, $this->Db_user, $this->Db_pswd)) {
            echo "连接数据库{$this->Db_host}失败,具体错误是:" . mysqli_connect_error();
            die();
        }
    }

    //私有的成员方法2
    private function selectDb()
    {
        if (!mysqli_select_db($this->link, $this->Db_name)) {
            echo "选择{$this->Db_host}数据库失败,具体错误是:" . mysqli_connect_error();
            die();
        }
    }

    //公共的析构方法
    public function __destruct()
    {
        mysqli_close($this->link);
    }

    //私有的克隆方法
    private function __clone()
{

}

    //公共的静态的创建对象的成员方法:这个方法必须公共权限,否则外部无法创建唯一的对象
    public static function startDb($config = array())
    {
        //判断obj对象是否存在,如果不存在就创建一个
        if (!self::$obj instanceof self) {
            self::$obj = new self($config);
        }
        return self::$obj;
    }
}
;

$arr = array(
    "Db_host" => "localhost",
    "Db_user" => "username",
    "Db_pswd" => "password",
    "Db_name" => "DB_name"
);
$DB1 = Db::startDb($arr);//不是new对象,而是调用公共的静态的创建对象的成员方法