談php設計模式介紹——偽對象模式(3)_PHP教程

      編輯Tag賺U幣
      教程Tag:暫無Tag,歡迎添加,賺取U幣!

      推薦:解析php字符串處理函數
      addcslashes 為字符串里面的部分字符添加反斜線轉義字符 addslashes 用指定的方式對字符串里面的字符進行轉義 bin2hex 將二進制數據轉換成十六進制表示 chr 返回一個字符的ASCII碼 chunk_split 按一定的字符長度將字符串分割成小塊 convert_cyr_string 將斯

      重構已有程序

      下面讓我們用偽對象來幫助重構一個已有程序。考慮一個簡單的腳本,它可以模擬你在無數的PHP程序中所期望的行為:例如一個當檢查到你未登錄時要求登錄的頁面;與此類似的還有表單處理頁面;它能在成功登錄后顯示不同內容并提供登出的功能。 讓我們寫一個這樣的頁面。首先,對還未登錄的用戶顯示一個登錄表單。

      <html>

      <body>

      <form method=”post”>

      Name:<input type=”text” name=”name”> Password:<input type=”password” name=”passwd”>

      <input type=”submit” value=”Login”>

      </form>

      </body>

      </html>

      接著,顯示登錄成功后的內容:

      <html>

      <body>Welcome <?php echo $_SESSION[‘name’]; ?>

      <br>Super secret member only content here.

      <a href=”<?php echo SELF; ?>?clear”>Logout</a>

      </body>

      </html>

      加入表單處理的功能,session(會話)開始,還有登出的功能,整體看起來應該類似這樣:

      session_start();

      define(‘SELF’,

      ‘http://’.$_SERVER[‘SERVER_NAME’].$_SERVER[‘PHP_SELF’]);

      if (array_key_exists(‘name’, $_REQUEST)

      && array_key_exists(‘passwd’, $_REQUEST)

      && ‘admin’ == $_REQUEST[‘name’]

      && ‘secret’ == $_REQUEST[‘passwd’]) {

      $_SESSION[‘name’] = ‘admin’;

      header(‘Location: ‘.SELF);

      }

      if (array_key_exists(‘clear’, $_REQUEST)) {

      unset($_SESSION[‘name’]);

      }

      if (array_key_exists(‘name’, $_SESSION)

      && $_SESSION[‘name’]) { ?>

      <html>

      <body>Welcome <?=$_SESSION[‘name’]?>

      <br>Super secret member only content here.

      <a href=”<?php echo SELF; ?>?clear”>Logout</a>

      </body>

      </html> <?php

      } else { ?>

      <html>

      <body>

      <form method=”post”>

      Name:<input type=”text” name=”name”> Password:<input type=”password” name=”passwd”>

      <input type=”submit” value=”Login”>

      </form>

      </body>

      </html> <?php

      }

      重構這個程序的一個目的應該是使其成為一個“易于測試”的程序。基于這個目的,如果你還選擇一些PHP中的方便特性——如超級全局變量——你將失去測試上的簡潔性。

      例如,如果你直接就用了$_SESSION,即意味著只有一種途徑可以測試這個代碼,就是改變$_SESSION。如果你忘了將$_SESSION改回先前已知的狀態,各種測試間就會互相干擾。

      一個好的解決方法是封裝$_SESSION到另一個類中,傳遞所封裝類的實例到任何想要訪問$_SESSION的對象。如果你創建了一個已封裝對象的偽對象用于測試,你能夠完全控制對象對所調用方法的響應(就像ServerStub那樣)并且你能核實它是如何調用的(那正是創建偽對象的目的)。

      具備了這個思想,讓我們看看如何封裝$_SESSION之類的全局變量。

      class Session {

      function Session() {

      $this->init();

      }

      function init() {

      if (!isset($_SESSION)) {

      if (headers_sent()) {

      trigger_error(

      ‘Session not started before creating session object’);

      } else {

      session_start();

      }

      }

      }
      function isValid($key) {
      return array_key_exists($key, $_SESSION);
      }
      function get($key) {

      return (array_key_exists($key, $_SESSION))

      ? $_SESSION[$key]

      : null;

      }

      function set($key, $value) {

      $_SESSION[$key] = $value;

      }
      function clear($key) {

      unset($_SESSION[$key]);

      }

      }

      類Session封裝了全局變量$_SESSION。對類SESSION的測試非常類似于對前期的已注冊的類的改良測試(參見第5章),但是卻無任何通過參數獲得或設置相應值的意圖。

      你也許注意到了構造函數調用了Session::init()方法。為什么這個方法不是構造函數的一部分呢?這樣分開的好處是你能靜態調用它并確保session已經開始。下面是一個如何使用該類的例子。

      Session::init();

      $page =& new PageDirector(new Session);

      大部分測試方面的文獻很推崇偽對象并建議你親自寫一個。如果你打算那樣做,開始測試時你就只需要充實那些你需要的方法就可以了。譬如,一個用于處理代碼的ServerStub的Session類很可能是這樣的:

      class MyMockSessionUser1 {

      function isValid($key) {

      return (‘user_id’ == $key) ? true : false;

      }

      function get($key) {

      if (‘user_id’ == $key) {

      return 1;

      }

      }

      }

      幸運的是,你可以用SimpleTest來避免那些易范的錯誤。Mock::generate()方法允許你創建一個類來實例化或動態地配置你想要的結果。

      注:偽對象技術
      SimpleTest所使用的方法僅是偽對象的多種用法之一。偽對象的代碼傳遞是另一種。隨著PHP5的到來,你也許能看到偽對象以對象中的__call()方法來執行。

      以下是如何用SimpleTest生成的偽對象來測試并重構MyMockSessionUser1類(如上例中)。

      Mock::Generate(‘Session’);

      class PageDirectorTestCase extends UnitTestCase {

      function testSomethingWhichUsesSession() {

      $session =& new MockSession($this);

      $session->setReturnValue(‘isValid’, true);

      $session->setReturnValue(‘get’, 1);

      // ...

      }

      }

      分享:怎樣把握技巧開發PHP網站
      1.使用 ip2long() 和 long2ip() 函數來把 IP 地址轉化成整型存儲到數據庫里。這種方法把存儲空間降到了接近四分之一(char(15) 的 15 個字節對整形的 4 個字節),計算一個特定的地址是不是在一個區段內頁更簡單了,而且加快了搜索和排序的速度(雖然有時僅

      來源:模板無憂//所屬分類:PHP教程/更新時間:2009-06-20
      相關PHP教程