<output id="r87xx"></output>
    1. 
      
      <mark id="r87xx"><thead id="r87xx"><input id="r87xx"></input></thead></mark>
        •   

               當(dāng)前位置:首頁(yè)>軟件介紹>php設(shè)計(jì)模式介紹之單條模式 查詢:
               
          php設(shè)計(jì)模式介紹之單條模式

                  幾乎所有面向?qū)ο蟮某绦蛑?,總有一兩個(gè)資源被創(chuàng)建出來(lái),在程序應(yīng)用中持續(xù)被共享使用。例如,這樣的一個(gè)資源,在一個(gè)電子商務(wù)程序的數(shù)據(jù)庫(kù)連接中使用:這個(gè)連接在應(yīng)用程序啟動(dòng)時(shí)初始化,程序于是可以有效的執(zhí)行;當(dāng)程序結(jié)束時(shí),這個(gè)連接最終被斷開(kāi)并銷毀。如果是你寫(xiě)的代碼,沒(méi)必要在每時(shí)每刻創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)連接,這樣非常低效。已經(jīng)建立好的連接應(yīng)該能被你的代碼簡(jiǎn)單重復(fù)的使用。這個(gè)問(wèn)題就是,基于以上要求你將如何進(jìn)行這個(gè)數(shù)據(jù)庫(kù)連接,(或者連接其它被循環(huán)使用的唯一資源,比如一個(gè)開(kāi)放文件或者一個(gè)隊(duì)列。) 問(wèn)題你怎樣確保一個(gè)特殊類的實(shí)例是獨(dú)一無(wú)二的(它是這個(gè)類的唯一實(shí)例),并且它很存取容易呢

                  解決方案

                  當(dāng)然,全局變量是顯而易見(jiàn)的解決方案。但它就像潘多拉的盒子(正確的判斷來(lái)自經(jīng)驗(yàn),而錯(cuò)誤的判斷產(chǎn)生經(jīng)驗(yàn)。這句諺語(yǔ)就是這個(gè)意思。),你的任何代碼都能修改全局變量,這將不可避免的引起更多調(diào)試的意外。換句話說(shuō),全局變量的狀態(tài)總是會(huì)出現(xiàn)一些問(wèn)題的,(這里有一個(gè)關(guān)于全局變量使用問(wèn)題不錯(cuò)的描述,)。 當(dāng)你需要一個(gè)特殊類的唯一實(shí)例時(shí),使用這個(gè)名字叫單件的模式?;趩渭J降念惸軐?shí)例化和初始化這個(gè)類的一個(gè)實(shí)例,并且提供每時(shí)每刻絕對(duì)相同的連接。一般情況下使用名為getInstance()的靜態(tài)方法實(shí)現(xiàn)。

                  關(guān)鍵問(wèn)題是,如何在每時(shí)每刻獲得一個(gè)精確統(tǒng)一的實(shí)例。請(qǐng)看下面的例子: // PHP4

                  function TestGetInstance() {

                  $this->assertIsA(

                  $obj1 =& DbConn::getInstance(), ‘DbConn’,

                  ‘The returned object is an instance of DbConn’);

                  $this->assertReference(

                  $obj1,

                  $obj2 =& DbConn::getInstance(), ‘Two calls to getInstance() return the same object’);

                  }

                  注釋:assertReference

                  assertReference() 方法確保兩個(gè)被傳遞的參數(shù)引用自相同的PHP變量。

                  在PHP4中,這里斷言兩個(gè)被測(cè)試的參數(shù)的卻是相同的對(duì)象。assertReference() 這個(gè)方法在移植到PHP5以后也許就不推薦使用了。

                  這個(gè)test方法有兩個(gè)斷言:第一個(gè)判斷第調(diào)用靜態(tài)方法DbConn::getInstance()返回的值是DbConn對(duì)象的實(shí)例,第二個(gè)用來(lái)判斷第二次調(diào)用getInstance()方法返回得值引用的是相同的對(duì)象實(shí)例,這意味著他們使用的是同一個(gè)對(duì)象。

                  除了斷言代碼預(yù)期的執(zhí)行結(jié)果,Test也預(yù)示了getInstance()的正確用法(PHP4):$local_conn_var=&DbConn::getInstance()。引用(=&)靜態(tài)方法的返回值賦值給了這個(gè)局部變量。

                  再寫(xiě)另外一段測(cè)試代碼:直接用“new”來(lái)實(shí)例化一個(gè)單件類會(huì)引起某些類型的錯(cuò)誤。test代碼如下:

                  function TestBadInstantiate() {

                  $obj =& new DbConn;

                  $this->assertErrorPattern(

                  ‘/(bad|nasty|evil|do not|don’t|warn).*’.

                  ‘(instance|create|new|direct)/i’);

                  }

                  這段代碼直接創(chuàng)建了一個(gè) DbConn 的實(shí)例,將會(huì)引起PHP報(bào)錯(cuò)。為了讓代碼更穩(wěn)定,我們用PCRE正則表達(dá)式來(lái)匹配報(bào)錯(cuò)信息。(顯示報(bào)錯(cuò)信息的確切措詞并不重要。)

                  樣本代碼

                  單件模式是一個(gè)很有趣的模式。讓我們用PHP4和PHP5兩種方式來(lái)探究它的實(shí)現(xiàn)過(guò)程,現(xiàn)在從PHP4開(kāi)始。

                  全局方式

                  理論上說(shuō),一個(gè)全局變量可以生成一個(gè)完美的單件,但全局變量可能被修改:在代碼運(yùn)行過(guò)程中,不能保證全局變量指向的是一個(gè)對(duì)象。因而,不讓全局變量在全局直接引用,就可以減少“太隨意訪問(wèn)”這個(gè)全局變量的問(wèn)題。比如說(shuō),這段代碼使用一個(gè)非常長(zhǎng)而且獨(dú)特的名字,從而“隱藏”了全局變量的引用。

                  class DbConn {

                  function DbConn($fromGetInstance=false) { if (M_E != $fromGetInstance) {

                  trigger_error(‘The DbConn class is a Singleton,’

                  .’ please do not instantiate directly.’);

                  }

                  }

                  function &getInstance() {

                  $key = ‘__some_unique_key_for_the_DbConn_instance__’;

                  if (!(array_key_exists($key, $GLOBALS) && is_object($GLOBALS[$key])

                  && ‘dbconn’ == get_class($GLOBALS[$key]) )) {

                  $GLOBALS[$key] =& new DbConn(M_E); }

                  return $GLOBALS[$key];

                  }

                  }

                  在DbConn的構(gòu)造函數(shù)中,你可能對(duì)$fromGetInstance的默認(rèn)參數(shù)感到疑惑。在對(duì)象被直接實(shí)例化時(shí),它能夠提供(很微弱的)保護(hù):除非這個(gè)默認(rèn)值變成e (在PHP的數(shù)學(xué)常量中 M_E , 2.718281828459),否則這段代碼會(huì)報(bào)錯(cuò)。

                  表示成一個(gè)UML類圖,解決辦法如下:

                  

                  如果你不選用這個(gè)“神秘參數(shù)”,類型保護(hù),建立一個(gè)全局標(biāo)記是另外一個(gè)選擇,用它來(lái)驗(yàn)證你是通過(guò)getInstance()方法來(lái)創(chuàng)建的對(duì)象。保護(hù)方式從“你知道它的名字”改變成“它存在于環(huán)境中”。

                  下面有個(gè)例子,它解釋了為什么構(gòu)造函數(shù)保護(hù)代碼有一個(gè)全局的標(biāo)識(shí): class DbConn {

                  function DbConn() {

                  $token = ‘__some_DbConn_instance_create_semaphore__’;

                  if (!array_key_existwww.shanxiwang.nets($token, $GLOBALS)) {

                  trigger_error(‘The DbConn class is a Singleton,’.’ please do not instantiate directly.’);

                  }

                  }

                  function &getInstance() {

                  static $instance = array();

                  if (!$instance) {

                  $token = ‘__some_DbConn_instance_create_semaphore__’;

                  $GLOBALS[$token] = true;

                  $instance[0] =& new DbConn;

                  unset($GLOBALS[$token]);

                  }

                  提示

                  PHP4允許你改變構(gòu)造函數(shù)中$this的值。在過(guò)去,我們會(huì)習(xí)慣設(shè)置 $this , null;當(dāng)有一個(gè)創(chuàng)建構(gòu)造錯(cuò)誤時(shí),確保無(wú)效的對(duì)象不能被代碼繼續(xù)使用。PHP4中很有用的東西,在PHP5中并不兼容,將來(lái)會(huì)在你的代碼中得到驗(yàn)證,這種技術(shù)不再被推薦。

                  這段代碼中另外一個(gè)重點(diǎn)是引用操作&的用法。有兩種地方需要使用&。第一種是在函數(shù)定義時(shí),在函數(shù)名字前用來(lái)表示將返回一個(gè)引用。第二種是將新的DbConn對(duì)象賦值給$GLOBALS數(shù)組。(在序言和值對(duì)象章節(jié)中提到過(guò):在PHP4中,你總會(huì)使用&操作符,以引用的方式創(chuàng)建、傳遞和返回對(duì)象,)

                  getInstance()方法的條件檢查,常常被寫(xiě)成沒(méi)有警示的情況下運(yùn)行,甚至在E_ALL的錯(cuò)誤級(jí)別下也不會(huì)提示。它檢查在$GLOBAL數(shù)組中適當(dāng)?shù)奈恢檬欠裼幸粋€(gè)DbConn對(duì)象,如果沒(méi)有,就在那里創(chuàng)建這個(gè)對(duì)象。這個(gè)方法于是返回了這樣的結(jié)果,這個(gè)對(duì)象能被重復(fù)創(chuàng)建或者這個(gè)對(duì)象在之前已經(jīng)被這個(gè)方法創(chuàng)建過(guò)了。當(dāng)方法結(jié)束時(shí),你可以確認(rèn)已經(jīng)擁有這個(gè)類的有效實(shí)例,而且它已經(jīng)被有效初始化。

                  靜態(tài)方式

                  關(guān)于全局變量的問(wèn)題,甚至隱藏在getInstance()中的全局變量中也存在。因?yàn)槿肿兞吭谀_本的任何地方都有效,在沒(méi)有注意到的情況下,你依然有可能破壞這個(gè)全局變量, 在getInstance()方法內(nèi)部使用靜態(tài)變量來(lái)存儲(chǔ)Singleton是一個(gè)顯得干凈的辦法。第一個(gè)代碼片斷如下:

                  class DbConn {

                  // ...

                  function &getInstance() {

                  static $instance = false;

                  if (!$instance) $instance =& new DbConn(M_E); return $instance;

                  }

                  }

                  Zend 1引擎在PHP4中不能存儲(chǔ)靜態(tài)變量的引用。使用一個(gè)工作區(qū)存儲(chǔ)靜態(tài)數(shù)組,并且將這個(gè)單件實(shí)例的引用放置到一個(gè)已知的數(shù)組中。getInstance()方法如下:

                  class DbConn {

                  function DbConn($fromGetInstance=false) { if (M_E != $fromGetInstance) {

                  trigger_error(‘The DbConn class is a Singleton,’

                  .’ please do not instantiate directly.’);

                  }

                  }

                  function &getInstance() {

                  static $instance = array();

                  if (!$instance) $instance0 =& new DbConn(M_E); return $instance0;

                  }

                  }

                  這段代碼很簡(jiǎn)單的選擇了這個(gè)靜態(tài)數(shù)組$instancede的第一個(gè)元素,用來(lái)保持單件DbConns實(shí)例的引用。

                  雖然這段代碼有點(diǎn)依賴PHP的布爾方式,但它比那個(gè)全局版本更嚴(yán)謹(jǐn):在條件檢測(cè)時(shí),使用一個(gè)空的數(shù)組會(huì)得到結(jié)果false。就像在DbConn類的前一個(gè)版本一樣,在函數(shù)的定義和賦值部分需要引用操作符。

                  PHP5中的單件模式

                  PHP5中更容易實(shí)現(xiàn)單件模式,PHP5對(duì)于類內(nèi)部變量和函數(shù)的訪問(wèn)控制被加強(qiáng)了。將DbConn::_construct()構(gòu)造方法設(shè)置為私有(private),這個(gè)類就不能被直接實(shí)例化。用UML圖表示,PHP5的DbConn單件模式如下:

                  組合使用靜態(tài)方法和靜態(tài)變量保持這個(gè)實(shí)例,并且設(shè)置構(gòu)造函數(shù)為私有,以防止直接實(shí)例化類而創(chuàng)建實(shí)例,代碼如下:

                  class DbConn {

                  /**

                  * static property to hold singleton instance

                  */

                  static $instance = false;

                  /**

                  * constructor

                  * private so only getInstance() method can instantiate

                  * @return void

                  */

                  private function __construct() {} /**

                  * factory method to return the singleton instance

                  * @return DbConn

                  */

                  public function getInstance() { if (!DbConn::$instance) {

                  DbConn::$instance = new DbConn; }

                  return DbConn::$instance;

                  }

                  }

                   

                  


          安全配置PHP的25個(gè)實(shí)踐事例php總結(jié)報(bào)告
          PHP+PDO+學(xué)習(xí)筆記PHP開(kāi)發(fā)中常見(jiàn)的錯(cuò)誤
          PHP+MySQL分頁(yè)原理及實(shí)現(xiàn)PHP連接各種數(shù)據(jù)庫(kù)代碼
          php程序員學(xué)習(xí)計(jì)劃PHP實(shí)現(xiàn)排序算法
          PHP程序員的技術(shù)成長(zhǎng)規(guī)劃php定時(shí)執(zhí)行任務(wù)的幾個(gè)方法
          PHP識(shí)別圖片主色調(diào)php編程與應(yīng)用
          php和js如何通過(guò)json互相傳遞數(shù)據(jù)php遞歸json類分享
          php中的有關(guān)錯(cuò)誤的配置有哪些PHP程序安全策略
          信息發(fā)布:廣州名易軟件有限公司 http://m.jetlc.com
          • 勁爆價(jià):
            不限功能
            不限用戶
            1998元/年

          • 微信客服

            <output id="r87xx"></output>
          1. 
            
            <mark id="r87xx"><thead id="r87xx"><input id="r87xx"></input></thead></mark>
              • 国产精品视频免费在线观看 | 欧洲精品久久久久 | 人人操超碰 | 亚洲精品视频成人 | 国产真实露脸乱子伦对白高清视频 | 日本在线视频色 | 成人黄片网 | PORNY九色视频9l自拍 | 草逼小视频| 免费看国产黄色视频 |