模式系列的開篇,首先介紹的是我最喜歡的單例模式(Singleton),簡單而言,這屬於:生成一個、且只生成一個對象實例的特殊類。segmentfault
這個惟一存在的類,將替代Global關鍵字,而且更安全。設計模式
全局變量是OOP程序猿遇到的主要BUG源泉之一,全局變量的衝突也是極其危險的,由於PHP不會對其產生任何級別的錯誤,若是結果不能直接觀測,那麼你的程序可能會讓你感到懵圈。安全
儘管命名空間的出現,必定程度上的避免了全局衝突,然而,在空間內的衝突仍然可能存在。可全部的類均可以訪問它,全局變量還是巨大的誘惑。測試
良好設計的系統:經過方法調用傳遞對象實例。this
每一個類都會與背景環境保持獨立,並經過清晰的通訊方式,與系統中其它部分進行無耦合協做。spa
但有時,你不得不經過 中間件 來溝通各個組件,中間件會致使依賴、耦合,而且,假若組件返回的參數之一,包含了這個中間件,將會致使「依賴污染」。設計
怎樣的中間件才能避免上述狀況呢?調試
如同Global,它能夠被全部對象使用;code
不存儲在全局變量中,不接受覆寫;面向對象設計模式
它在整個系統中,是惟一的。
爲了解決這個問題,咱們能夠強行控制「對象實例化」,咱們經過簡單地定義一個私有構造方法,建立一個沒法從外部實例化的類,經過靜態方法與靜態屬性,來間接實例化它:
class Preferences { private $props = array(); private static $instance; private function __construct() { } public static function getInstance() { if (empty(self::$instance)) { self::$instance = new Preferences(); } return self::$instance; } public function setProperty($key, $val) { $this->props[$key] = $val; } public function getProperty($key) { return $this->props[$key]; } }
單例類建立完畢後,咱們進行測試:
// 設置屬性 $pref = Preferences::getInstance(); $pref->setProperty("name", "UiTest"); unset($pref); // 調用屬性 $pref2 = Preferences::getInstance(); echo $pref2->getProperty("name");
最終能夠獲得輸出:UiTest,而且,你能夠去設置任何值,來測試它的可用性。
最後附贈一張UML圖:
(感謝雲繪圖軟件:ProcessOn)
Bad Result:單例與全局變量都會:建立難以調試的依賴關係、被誤用、繞過安全的通訊接口,因此,須要謹慎當心的部署單例類。
Nice Result:與全局變量不一樣,單例的任何錯誤與衝突,都將以報錯的形式出現(除非你關閉了錯誤提示),這下,你就能夠放心的使用它了。