PHP中的單例模式(可用於數據庫連接維護)

正文

在OOP中,一個對象只負責一個特定的任務通常是一種很好的做法。例如,你也許希望只讓一個對象去訪問數據庫。單例模式被認爲是職責模式,這是因爲它將創建對象的控制權委託到一個單一的訪問點上。

在任何時候,應用程序中都會只有這個類僅有的一個實例存在。

這可以防止我們去打開數據庫的多個連接,或者不必要得使用多餘的系統資源。

在更加複雜的系統中,使用單例模式在維持系統程序狀態的同步方面也尤其有用。

所有的單例模式至少擁有以下三個公共元素:

  • 它們必須擁有一個構造函數,並且被標記爲private。
  • 它們擁有一個保存類的實例的靜態成員變量。
  • 它們擁有一個訪問這個實例的公共的靜態方法。

和普通類不同的是,單例模式不能在其它類中直接實例化。單例模式只能被其自身實例化。要獲得這種限制效果,__construct()方法必須被標記爲private。如果試圖用private構造函數構造一個類,就會得到一個可訪問性級別的錯誤。

要讓單例類起作用,就必須使其爲其他類提供一個實例,用它調用各種方法。單例類不會創建實例副本,而是會向單例類內部存儲的實例返回一個引用。結果是單例類不會重複佔用內存和系統資源,從而讓應用程序的其他部分更好的使用這些資源。作爲這一模式的一部分,必須創建一個空的私有的__clone()方法,以防止對象唄複製或者克隆。

返回實例引用的這個方法通常被命名爲getInstance()。這個方法必須是靜態的,而且如果它還沒有實例化,就必須實例化。getInstance()方法通過使用instanceof操作符和self關鍵字,可以檢測到類是否已經被初始化。如果保存實例的靜態成員爲空或者還不是類自身的一個實例,那麼這個實例將會被創建並保存到存放實例的變量中。

示例

<?php

class UniqueRandNumber
{
    private $_num;
    static $_instance;

    ////$urn = new UniqueRandNumber();非法,因爲構造函數是私有的
    private function __construct()
    {
        echo "construct\n";
        $this->_num = rand(1, 100); //生成[1,100]之間的一個隨機整數
    }

    //將__clone()設置爲私有,則$urn2 = clone $urn1;這句話不合法
    private function __clone()
    {

    }

    public static function getInstance()
    {
        if(!(self::$_instance instanceof self)){
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    public function fetch()
    {
        return $this->_num;
    }
}

echo "getInstance1: \n";
$urn1 = UniqueRandNumber::getInstance();
echo "getInstance1: \n";
$urn2 = UniqueRandNumber::getInstance();

echo "\n";
echo $urn1->fetch()."\n";
echo $urn2->fetch()."\n";

輸出
getInstance1: 
construct
getInstance1: 

73
73

可以看出,兩次getInstance()只調用了一次構造函數。

數據庫連接單例模式

對於數據庫連接,一個例子是

<?php

class Database
{
    private $_db;
    static $_instance;

    private function __construct()
    {
        $dsn = '';
        $this->_db = new PDO($dsn);
    }

    private function __clone()
    {

    }

    public static function getInstance()
    {
        if(!(self::$_instance instanceof self)){
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    public function getPDO()
    {
        return $this->_db;
    }
}

$database = Database::getInstance();
$pdo = $database->getPDO();

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章