php設計模式總結-單件模式
一、單件模式
英文叫做sington。其他語言中有叫做單例模式,其實都是一樣的道理。保證只會出現單個例項,所以是單例。翻譯成單件,永遠只會產生一件,呵呵。
還有翻譯成單元素模式。其實關鍵是看這個英文比較好。英文是sington,統一是使用這個單詞。
單件模式的目的我理解如下:
避免重複建立(例項化)物件,已經有現成的例項就用現成的。
減少資源的浪費(因為建立多個例項,浪費記憶體,完全沒必要),單件模式保證了每時每刻引用的都是同一個例項。
為什麼同時建立多個例項會引起邏輯上的錯誤呢?
$obj1
$obj2
多個例項。可能會覆蓋掉裡面的靜態static變數嗎? 不是這樣子的。
其實是因為我目前還沒遇到更加嚴重的問題。目前是簡單的應用。
二、我覺得單件模式實踐的注意點在下面幾個方面
1、不要使用全域性變數來儲存例項值。因為全域性變數在任何地方都可以被訪問和修改,這就意味著可能會被其他程式碼給破壞掉值,這樣就達不到永遠是同一
個例項的效果。
2、使用static靜態變數。這樣只能函式內部訪問。解決了全域性變數被破壞的風險。
我覺得這是很多要做到例項唯一的一個關鍵部分。像框架中為保證所有對類例項的引用是唯一一個,都是將例項儲存在static變數中。這樣子下回撥用的
時候也是同一個例項。不會重複建立。
抓住了這個精髓,我覺得是可以變化的。並不一定要遵循設計模式書中的做法。因為目標是相同的。技巧可以不同。
3、一般將類的__construct()建構函式標識為private,這樣就是避免程式設計師直接例項化這個類。根據每種語言的特點,加上private關鍵詞,程式設計師new一
個物件,就會報錯。這種技巧是一種輔助手段。為保證只有一個類例項做輔助方案的。核心還是在於第二點的static關鍵字。
只要程式設計師約定好,這個輔助手段其實可以沒有仍然能夠做到單件。不是為設計模式而設計。瞭解實現目標才是關鍵的。
我在想,可以使用protected來替代嗎?
目標就是,要禁止使用new來例項化這個函式。當例項化一個類的時候,預設會去執行建構函式,而加上protected和private關鍵字的成員,
都同樣不能在類外部呼叫的。所以使用protected也是可行的。
但為什麼要使用private呢?還有個好處,可以避免被繼承的子類所重寫,覆蓋掉方法的內容。因為加上protected標識的成員是能夠被子類給重寫的。
既然對建構函式加上了private,那就意味著子類是不能繼承這個類的。瞭解這個特性設計的時候就要考慮,無子類繼承它的概念。
4、程式碼實踐
class test
{
static $_instance = false;
private function __construct()
{
/*一般將建構函式加上private關鍵字,這樣子避免直接使用外部直接new來例項物件,當然內部使用new來建立是不會影響的*/
}
function get_instance()
{
if(self::$_instance==false && !is_object(self::$_instance)){
self::$_instance = new test();
}
return self::$_instance;
}
}
實際專案開發中,有個變體是,建立a、b、c的例項都需要通過一個公共的方法來呼叫,這樣子可以實現單件模式。
類似於thinkphp等框架中的。
像下面是phpcms中的
pc_base::load_app_calss(`test`);
load_app_class($class_name)
{
static $class_array = array();
if(isset($class_array[$class_name]) && is_object($class_array[$class_name])) )
return $class_array[$class_name];
}else{
//這裡可能還要有程式碼載入這個類檔案,根據實際而定。可以是去預設一個資料夾夾中載入。也可以認為呼叫這個方法的前提是類檔案要載入進來
$class_array[$class_name] = new $class_array[$class_name];
return $class_array[$class_name];
}
其實可以避免建立很多資料庫連結。寫到這裡,我想起了mysql對於同一組引數進行的mysql_connect()連線,是不會重新建立連線的。php手冊中對這個函
數的解釋如下:
如果用同樣的引數第二次呼叫 mysql_connect(),將不會建立新連線,而將返回已經開啟的連線標識。
其實呢,只是mysql_connect這個函式做了可複用了。不討論資料庫連線方面。例項化其他的類,也需要建立大量的例項。佔有資源。是指同一次執行的代
碼過程中才能起到節省資源的效果
比如a.php的程式碼過程如下:
$class = test::get_instance();//得到這個test這個類的例項
$class->get_name();
get_count_number();//假設這個函式裡面又需要用到那個類,則又需要進行例項化,如果統一呼叫get_instance()來獲取例項,則前面得到的例項是可以
複用的。
三、單態模式(monostate)
1、單件模式還有一種變體:就是類的單件模式,也就是monostate模式。MonoState的意思就是”單一的狀態”。也就是常說的單態。實現的目標為:所有實
例都是共享類中同一個值。
monostate的設計目標為:實現多個例項可以共享變數(類裡面的屬性),成為單態,儘管存在多個例項,但例項中的變數的最終只會有一個狀態(可以理解為
一個值),不會出現多個值(也就是每個例項裡面的變數都是不同的值)。
2、它與單件的區別為:
單件是將建構函式宣告為private,來保證只有一個例項。而單態則不需要。它關注的側重點是最終只有一個數值,而使用者例項化多少類,不是它所關心的
。
MonoState並不限制建立物件的個數,但是它的狀態卻只有一個狀態。
3、monostate模式實踐
實踐要點:把類裡面的變數(屬性)標識為static即可
<?php
class test
{
static $_state = array();
function set($key,$value)
{
self::$_state[$key]= $value;
}
function get($key)
{
return self::$_state[$key];
}
}
$obj = new test();
$obj->set(`name`,`wangtao`);
$obj->set(`sex`,`male`);
echo $obj->get(`name`);//得到結果是wangtao
//再次例項化一次,看訪問物件的成員,是否得到一樣的資料。
$obj2 = new test();
echo $obj2->get(`name`);//輸出wangtao
//再次新建立一個例項$obj2,訪問name這個變數,資料是共享的,所以輸出還是wangtao。當然使用set()把值改變了,其他例項也會訪問到改變後的值。
總結:實現monostate模式,具體實現有多種辦法,只要達到共享資料的目的就ok。比如使用$_GLOABS[]全域性變數,把資料儲存在全域性變數中,然後放到類
成員中也可以,《php設計模式》這本書就是使用這種形式實現。使用靜態變數(static關鍵字)也可以。上面使用的就是靜態變數的方式。我覺得使用
static方式更加直觀易懂
四、思考:sington與monostate能混合一起實現嗎?
既然sington模式可以避免建立多個例項。而monostate是關注多個例項之間共享資料。
那麼有沒有種辦法讓兩者混合呢。
也就是說:我構造一個類,既能夠達到單件的效果,也能實現monostate的效果。開玩笑玩玩,呵呵,加深深入理解。
我覺得,單件關注的是例項化一個類。monostate關注的狀態的一致性。其實兩者是不相容的。
如果實現了單件模式。那麼就不存在多個例項物件存在。既然都是呼叫同一個例項,這樣子裡面的成員變數肯定是共享的,因為使用的是同一個例項的成員
。為此我特意做試驗,如下:
class test
{
static $_state;//實現單態,就是將裡面變數定義為static即可,現在這個類實現了monostate模式
static $_instance = false;
private function __construct()
{
}
/*
實現單例模式
*/
function get_instance()
{
if(self::$_instance==false && !is_object(self::$_instance)){
self::$_instance = new test();
}
return self::$_instance;
}
}
$obj1 = test::get_instance();
$obj1->_state = 20;
$obj2 = test::get_instance();//因為這裡引用的還是同一個例項,所以下面輸出屬性的值,還是前面更改的20
echo $obj2->_state;
以上是給自己總結用。不正確之處歡迎指正。
相關文章
- PHP設計模式總結PHP設計模式
- 設計模式總結 —— 單例設計模式設計模式單例
- php設計模式總結-工廠模式PHP設計模式
- PHP設計模式-- 單列模式PHP設計模式
- PHP設計模式_單例模式PHP設計模式單例
- PHP設計模式——單例模式PHP設計模式單例
- PHP設計模式學習最全總結PHP設計模式
- PHP 設計模式之單例模式PHP設計模式單例
- PHP 設計模式之——單例模式PHP設計模式單例
- PHP設計模式之單例模式PHP設計模式單例
- php模式設計之 單例模式PHP模式單例
- PHP設計模式之:單例模式PHP設計模式單例
- 《Head First 設計模式》:單件模式設計模式
- 設計模式總結(模式篇)設計模式
- 用到的設計模式總結--單例模式+工廠方法模式+Builder模式設計模式單例UI
- 設計模式簡單總結(待完善)設計模式
- Java中單例設計模式總結Java單例設計模式
- 設計模式--單件模式Singleton(建立型)設計模式
- 設計模式總結設計模式
- 設計模式系列——3.簡單工廠模式與策略模式總結設計模式
- 【php實現設計模式】之單例模式PHP設計模式單例
- PHP設計模式(四)單例模式(Singleton)PHP設計模式單例
- 設計模式大總結(六):命令模式設計模式
- JavaScript設計模式總結JavaScript設計模式
- 前端設計模式總結前端設計模式
- 【設計模式總結篇】設計模式
- PHP設計模式(一)簡單工廠模式 (Simple Factory For PHP)PHP設計模式
- PHP設計模式(一)—單例模式(Singleton Pattern)PHP設計模式單例
- PHP設計模式-代理模式PHP設計模式
- php設計模式–策略模式PHP設計模式
- 建立型設計模式對比總結 設計模式(八)設計模式
- PHP設計模式—建立型設計模式PHP設計模式
- C++設計模式 - 總結C++設計模式
- PHP結構型設計模式(下)PHP設計模式
- PHP結構型設計模式(上)PHP設計模式
- [設計模式]單例設計模式設計模式單例
- PHP 設計模式PHP設計模式
- php設計模式PHP設計模式