博主最近開始真正的潛心學習PHP的各種設計模式。剛開始當然從一些簡單的設計模式開始學起,比如之前發表的原廠模式,今天的單利模式,還有之後要看的註冊模式。其實這些都是比較基礎的設計模式,一些簡單的樣本一看就能明白,對於稍加複雜些的樣本,花點心思進去也能夠理解。可重點是,光是知道瞭解這麼個東西是不夠的,而是如何能夠把他更好的運用的項目中去,在實踐中增加熟練度。好吧,還是說說今天要看的單例模式吧。
一、什麼是單例模式?
1、含義:
作為對象的建立模式,單例模式確保某一個類只有一個執行個體,而且自行執行個體化並向整個系統全域地提供這個執行個體。它不會建立執行個體副本,而是會向單例類內部儲存的執行個體返回一個引用。
2、單例模式的三個要點:
(1)需要一個儲存類的唯一執行個體的靜態成員變數。
(2)建構函式和複製函數必須聲明為私人的,防止外部程式new類從而失去單例模式的意義。
(3)必須提供一個訪問這個執行個體的公用的靜態方法(通常為getInstance方法),從而返回唯一執行個體的一個引用。
假設我們目前需要設計一個資料庫訪問類,需要用到單例模式,看如下樣本:
<?phpclass DB { private $_db; private static $_instance; private function __construct(...) { $this->_db = pg_connect(...);//postgrsql } private function __clone() {}; //覆蓋__clone()方法,禁止複製 public static function getInstance() { if(!(self::$_instance instanceof self) ) { self::$_instance = new self(); } return self::$_instance; } public function sql(...) { /* * code */ }}$db = DB::getInstance(); $db->sql(); ?>
<111?111php111
/1**
* 設計模式之單例模式
* $_instance必須聲明為靜態私人變數
* 建構函式和解構函式必須聲明為私人,防止外部程式new
* 類從而失去單例模式的意義
* getInstance()方法必須設定為公有的,必須調用此方法
* 以返回執行個體的一個引用
* ::操作符只能訪問靜態變數和靜態函數
* new對象都會消耗記憶體
* 使用情境:最常用的地方是資料庫連接。
* 使用單例模式產生一個對象後,
* 該對象可以被其它眾多個物件所使用。
*/
class Danli {
//儲存類執行個體的靜態成員變數
private static $_instance;
//private標記的構造方法
private function __construct(){
echo 'This is a Constructed method;';
}
//建立__clone方法防止對象被複製複製
public function __clone(){
trigger_error('Clone is not allow!',E_USER_ERROR);
}
//單例方法,用於訪問執行個體的公用的靜態方法
public static function getInstance(){
if(!(self::$_instance instanceof self)){
self::$_instance = new self;
}
return self::$_instance;
}
public function test(){
echo '調用方法成功';
}
}
//用new執行個體化private標記建構函式的類會報錯
//$danli = new Danli();
//正確方法,用雙冒號::操作符訪問靜態方法擷取執行個體
$danli = Danli::getInstance();
$danli->test();
//複製(複製)對象將導致一個E_USER_ERROR
$danli_clone = clone $danli;
例子3
1、普通的資料庫訪問例子:
<?php ...... //初始化一個資料庫控制代碼 $db = new DB(...); //添加使用者資訊 $db->addUserInfo(...); ...... //在函數中訪問資料庫,尋找使用者資訊 function getUserInfo() { $db = new DB(...);//再次new 資料庫類,和資料庫建立串連 $db = query(....);//根據查詢語句訪問資料庫 } ?>
例子4、應用單例模式對資料庫進行操作:
<?php class DB { private $_db; private static $_instance; private function __construct(...) { $this->_db = pg_connect(...);//postgrsql } private function __clone() {}; //覆蓋__clone()方法,禁止複製 public static function getInstance() { if(! (self::$_instance instanceof self) ) { self::$_instance = new self(); } return self::$_instance; } public function addUserInfo(...) { } public function getUserInfo(...) { } } //test $db = DB::getInstance(); $db->addUserInfo(...); $db->getUserInfo(...); ?>
二、為什麼要使用單例模式?
1、PHP缺點:
PHP語言是一種解釋型的指令碼語言,這種運行機制使得每個PHP頁面被解釋執行後,所有的相關資源都會被回收。也就是說,PHP在語言層級上沒有辦法讓某個對象常駐記憶體,這和asp.net、Java等編譯型是不同的,比如在Java中單例會一直存在於整個應用程式的生命週期裡,變數是跨頁面級的,真正可以做到這個執行個體在應用程式生命週期中的唯一性。然而在PHP中,所有的變數無論是全域變數還是類的靜態成員,都是頁面級的,每次頁面被執行時,都會重建立立新的對象,都會在頁面執行完畢後被清空,這樣似乎PHP單例模式就沒有什麼意義了,所以PHP單例模式我覺得只是針對單次頁面級請求時出現多個應用情境並需要共用同一對象資源時是非常有意義的。
2、單例模式在PHP中的應用場合:
(1)應用程式與資料庫互動
一個應用中會存在大量的資料庫操作,比如過資料庫控制代碼來串連資料庫這一行為,使用單例模式可以避免大量的new操作,因為每一次new操作都會消耗記憶體資源和系統資源。
(2)控制配置資訊
如果系統中需要有一個類來全域控制某些配置資訊, 那麼使用單例模式可以很方便的實現.