轉(zhuǎn)自http://www.cnblogs.com/fangle/p/6830899.html
單例模式(Singleton Pattern):顧名思義,就是只有一個實例甚脉。作為對象的創(chuàng)建模式爬迟,單例模式確保某一個類只有一個實例芋忿,而且自行實例化并向整個系統(tǒng)提供這個實例吭净。
(一)為什么要使用PHP單例模式
1,php的應(yīng)用主要在于數(shù)據(jù)庫應(yīng)用, 一個應(yīng)用中會存在大量的數(shù)據(jù)庫操作, 在使用面向?qū)ο蟮姆绞介_發(fā)時, 如果使用單例模式,
則可以避免大量的new 操作消耗的資源,還可以減少數(shù)據(jù)庫連接這樣就不容易出現(xiàn) too many connections情況岩遗。
2吩坝,如果系統(tǒng)中需要有一個類來全局控制某些配置信息, 那么使用單例模式可以很方便的實現(xiàn). 這個可以參看zend Framework的FrontController部分。
3缠诅,在一次頁面請求中, 便于進行調(diào)試, 因為所有的代碼(例如數(shù)據(jù)庫操作類db)都集中在一個類中, 我們可以在類中設(shè)置鉤子, 輸出日志溶浴,從而避免到處var_dump, echo
(二)單例模式UML圖
Singleton Pattern
(三)單例模式的實現(xiàn)
1,私有化一個屬性用于存放唯一的一個實例
2管引,私有化構(gòu)造方法士败,私有化克隆方法,用來創(chuàng)建并只允許創(chuàng)建一個實例
3褥伴,公有化靜態(tài)方法谅将,用于向系統(tǒng)提供這個實例
(四)代碼實現(xiàn)
class Singleton
{
? ? ? ? ? ? ?//存放實例
? ? ? ? ? ? ? privatestatic$_instance=null;
? ? ? ? ? ? ?//私有化構(gòu)造方法、
? ? ? ? ? ? ?privatefunction__construct(){
? ? ? ? ? ? ? ?echo"單例模式的實例被構(gòu)造了";
} ? ? ? ? ??
? ? ? ? //私有化克隆方法privatefunction__clone(){
}//公有化獲取實例方法publicstaticfunctiongetInstance(){if(!(self::$_instanceinstanceof Singleton)){
self::$_instance=newSingleton();
}returnself::$_instance;
}
}$singleton=Singleton::getInstance();
優(yōu)點:因為靜態(tài)方法可以在全局范圍內(nèi)被訪問重慢,當(dāng)我們需要一個單例模式的對象時饥臂,只需調(diào)用getInstance方法,獲取先前實例化的對象似踱,無需重新實例化隅熙。
(五)使用Trait關(guān)鍵字實現(xiàn)類似于繼承單例類的功能
Trait Singleton{//存放實例privatestatic$_instance=null;//私有化克隆方法privatefunction__clone(){
}//公有化獲取實例方法publicstaticfunctiongetInstance(){$class=__CLASS__;if(!(self::$_instanceinstanceof$class)){
self::$_instance=new$class();
}returnself::$_instance;
}
}classDB {privatefunction__construct(){echo__CLASS__.PHP_EOL;
}
}classDBhandleextendsDB {useSingleton;privatefunction__construct(){echo"單例模式的實例被構(gòu)造了";
}
}$handle=DBhandle::getInstance();//注意若父類方法為public,則子類只能為pubic核芽,若父類為private囚戚,子類為public ,protected轧简,private都可以驰坊。
補充,大多數(shù)書籍介紹單例模式哮独,都會講三私一公拳芙,公優(yōu)化靜態(tài)方法作為提供對象的接口假勿,私有屬性用于存放唯一一個單例對象。私有化構(gòu)造方法态鳖,私有化克隆方法保證只存在一個單例转培。
但實際上,雖然我們無法通過new 關(guān)鍵字和clone出一個新的對象浆竭,但我們?nèi)粝氲玫揭粋€新對象浸须。還是有辦法的,那就是通過序列化和反序列化得到一個對象邦泄。私有化sleep()和wakeup()方法依然無法阻止通過這種方法得到一個新對象删窒。或許真得要阻止顺囊,你只能去__wakeup添加刪除一個實例的代碼肌索,保證反序列化增加一個對象,你就刪除一個特碳。不過這樣貌似有點怪異诚亚。
后續(xù)更新,歡迎大家評論指正
歡迎大家關(guān)注我的微信公眾號 火風(fēng)鼎