模式對於OOP開發人員尤其有用,因為他有助於建立穩定的API,並且仍然保持一定的靈活度。一種模式可以協助我們定義負責完成特定任務的對象,還可以允許我們全部修改掉某個類而不用修改與這些類打交道的代碼。前者被稱為類的職責,後者被稱為類的多態性。
單例模式被當作職責模式,他用來在應用程式中建立一個單一的功能訪問點。它將建立對象的控制權委託到一個單一的訪問點上。在任何時候,應用程式中都只會有這個類僅有的一個執行個體存在。這可以防止我們去開啟資料庫的多個串連或者不必要得使用多餘的系統資源。在更加複雜的系統中,使用單例模式在維持應用程式狀態的同步方面也尤其有用。
所有的單例類至少擁有以下三種公用元素:
它們必須擁有一個建構函式,並且必須被標記為private。
它們擁有一個儲存類的執行個體的靜態成員變數。
它們擁有一個訪問這個執行個體的公用的靜態方法
和普通類不同的是,單例類不能在其他類中直接執行個體化。單例類只能被其自身執行個體化。要獲得這樣的一種結果, __construct()方法必須被標記為private。如果試圖用private建構函式構造一個類,就會得到一個可訪問性層級的錯誤。
要讓單例類起作用,就必須使其為其他類提供一個執行個體,用它調用各種方法。單例類不會建立執行個體副本,而是會向單例類內部儲存的執行個體返回一個引用。結果是單例類不會重複佔用記憶體和系統資源,從而讓應用程式的其它部分更好地使用這些資源。作為這一模式的一部分,必須建立一個空的私人__clone()方法,以防止對象被複製或複製。
返回執行個體引用的這個方法通常被命名為getTnstance()。這個方法必須是靜態,而且如果它還沒有執行個體化,就必須進行執行個體化。getInstance() 方法通過使用 instanceof 操作符和self 關鍵字,可以檢測到類是否已經被執行個體化。
/* 例子:資料庫連接職責的集中控制 */
class Database {
private $_db;
static $_instance;
private function __construct() {
$this->_db = pg_connect('dbname=example_db');
}
private __clone() {};
public static function getInstance() {
if( ! (self::$_instance instanceof self) ) {
self::$_instance = new self();
}
return self::$_instance;
}
public function query($sql) {
// 使用 $this->_db 執行一個查詢
return pg_query($this->_db, $sql);
}
}