今天我們一起來學習單例模式:
學一個模式,我們總要知道應用的場景吧。不然,就好比學一門武功招式,若不知道在何種情況下使用,豈不是枉費功夫呀。
對於單例模式,最常見的一個應用就是數據庫連接。如果每打開一個網頁,就建一個鏈接,那這種銷耗是很大的一個浪費。所以我們需要用單例模式來確保系統只有在必要的時候才建立新連接。
如果用偽代碼來描述單例模式,可以這樣寫:
if(連接存在){
返回該鏈接
}else{
建立一個新鏈接
}
但是這樣實現顯然是有問題的,這個鏈接要怎麼保存,才可以被外部訪問,同時又可以不被外部破壞。這個如果是用php來實現的話,是很容易的。我們一起來看一段代碼:
//get data class class DB { private $_db; private static $_instance; private function __construct(){ $DSN = '../../content/xxtebook.db'; $this->_db = new PDO('sqlite:'.$DSN); } //初始化數據庫連接 public static function initDB(){ if(! (self::$_instance instanceof self)){ self::$_instance = new self(); } return self::$_instance; } //其它方法 }
為什麼要把構造函數進行私有化呢?這個問題問的很好,歡迎大家提出這樣的疑問哈。
首先,做為單例,就是要避免被外部意外的創建新的實例。通過內部的方法進行實例的創建工作,可以確保這一點。而且內部方法訪問內部的變量,具有先天性的優勢。
其實我們可以把實例的結時保存在類的內部,這樣下次在檢到這個值的存在時,可以直接取出使用,而不需要再重新創建。
當然,我看到有些書上,做了一個空的 __clone(){}方法,防止克隆,這是很好的。錦上添花的事情,我就留到具體的項目上去做了。
最後我們來看看怎麼用這個單例:
$db = DB::initDB(); //$db->somMethod();
是不是非常的簡單呢。
另外對於哪些方法用靜態,哪些方法不用,我的想法就是,如果方法內部要訪問$this變量的,那麼就不應當用靜態方法,反之則可以用靜態。也就是說,靜態方法不需要通過例實對象就可以使用。
下一次我們再一起學習工廠模式