《PHP設計模式介紹》第三章 工廠模式(8)_PHP教程

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

      推薦:《PHP設計模式介紹》第二章 值對象模式
      在所有的最簡單的程序中,大多數對象都有一個標識,一個重要的商業應用對象,例如一個Customer或者一個SKU,有一個或者更多的屬性---id,name,email地址,這樣可以把它從同一個類的其他實例區分開

      別把話題扯遠了。那么如何才在黑匣子和白匣子之間找到折中辦法來實現TDD呢呢?一種選擇就是使原來的類中的私有方法變為公有,并且在發布的時候變回私有。但這并不是十分令人滿意的方式,所以我們建立一個子類,同時使子類中的方法可以從外部訪問:

      下面就是一個子類的例子:

      class TestableAssessor extends Assessor {
      public function getPropInfo($name) {
      return Assessor::getPropInfo($name);
      }
      }

      這樣做的好處是你可以得到正確的Assessor公有接口(API), 但通過 TestableAssessor 類我們就可以來測試Assessor類了。另外, 你用于測試的代碼也不會影響到Assessor類。

      缺點是:外加的類會帶來更多的問題,從而使測試變得更復雜。而且如果你在對象中的一些內部接口作出一些改動, 你的測試將隨著你的重構而再次失效。

      比較了它的優點和缺點,讓我們來看看它的測試方法:

      function testGetPropInfoReturn() {
      $assessor = new TestableAssessor;
      $this->assertIsA(
      $assessor->getPropInfo(‘Boardwalk’), ‘PropertyInfo’);
      }

      為了要保證所有代碼的正確執行, 我們可以使用異常處理。 SimpleTest的目前是基于PHP4 搭建的測試的結構,所以不具備異常處理能力。但是你還是可以在測試中使用如下。

      function testBadPropNameReturnsException() {
      $assessor = new TestableAssessor;
      $exception_caught = false;
      try { $assessor->getPropInfo(‘Main Street’); }
      catch (InvalidPropertyNameException $e) {
      $exception_caught = true;
      }
      $this->assertTrue($exception_caught);

      最后, Assessor類的執行部分完成了:

      class Assessor {
      protected $game;
      public function setGame($game) { $this->game = $game; }
      public function getProperty($name) {
      $prop_info = $this->getPropInfo($name);
      switch($prop_info->type) {
      case ‘Street’:
      $prop = new Street($this->game, $name, $prop_info->price);
      $prop->color = $prop_info->color;
      $prop->setRent($prop_info->rent);
      return $prop;
      case ‘RailRoad’:
      return new RailRoad($this->game, $name, $prop_info->price);
      break;
      case ‘Utility’:
      return new Utility($this->game, $name, $prop_info->price);
      break;
      default: //should not be able to get here
      }
      }
      protected $prop_info = array(/* ... */);
      protected function getPropInfo($name) {
      if (!array_key_exists($name, $this->prop_info)) {
      throw new InvalidPropertyNameException($name);
      }
      return new PropertyInfo($this->prop_info[$name]);
      }
      }

      Assessor::getPropInfo()方法從邏輯上說明 PropertyInfo工廠類是作為了Assessor類的一個私有的方法。而Assessor::getProperty() 方法是用來返回三個Property子類的一個,至于返回哪一個子類這要看property的名字。

      遲加載(Lazy Loading)的工廠

      使用工廠的另一個好處就是它具有遲加載的能力。這種情況常被用在:一個工廠中包括很多子類,這些子類被定義在單獨的PHP文件內。

      注:術語 - 遲加載
      在遲加載模式中是不預加載所有的操作(像包含PHP文件或者執行數據庫查詢語句),除非腳本中聲明要加載。

      用一個腳本可以有效地控制多個網頁的輸出,這是Web常用的方法了。比如一個博客程序,一些入口就有不同的頁面來實現,一個簡單的評論入口就有:發布評論的頁面,一個導航的頁面,一個管理員編輯的頁面等。 你可以把所有的功能放入一個單獨的類中,使用工廠來加載他們。每一個功能類可以單獨放在一個文件里,再把這些文件都放在“pages”這個子文件夾里,這樣可以方便調用。

      實現遲加載的頁面工廠(page factory)的代碼可以寫作:

      class PageFactory {
      function &getPage() {
      $page = (array_key_exists(‘page’, $_REQUEST))
      ? strtolower($_REQUEST[‘page’])
      : ‘’;
      switch ($page) {
      case ‘entry’: $pageclass = ‘Detail’; break;
      case ‘edit’: $pageclass = ‘Edit’; break;
      case ‘comment’: $pageclass = ‘Comment’; break;
      default:
      $pageclass = ‘Index’;
      }
      if (!class_exists($pageclass)) {
      require_once ‘pages/’.$pageclass.’.php’;
      }
      return new $pageclass;
      }
      }

      你可以利用 PHP 的動態加載性質,然后使用實時的運行需求(run-time)來給你要建立的類命名。在這情況下, 根據一個 HTTP 請求叁數就能確定哪個頁面被加載。你可以使用遲加載,這樣只要當你需要建立新對象時才載入相應的類,不需要你載入所有可能用到的“page”類。在上述例子中就用了 require_once來實現這一點。這個技術對于一個裝有PHP加速器的系統來說并不重要,因為包含一個外加的文件使用的時間對它來說可以忽略。 但對于大多數典型的PHP服務器來說,這樣做是很有好處的。

      要想了解更多的關于遲加載的知識,請看第 11 章-代理模式。

      小節

      工廠模式是非常簡單而且非常有用。如果你已經有很多關于工廠模式的例子代碼,你會發現更多的東西。《GoF》這本書就介紹了一些關于構建的模式:AbstractFactory and Builder。 AbstractFactory用來處理一些相關組件,Builder模式則是使建立復雜對象更為容易。

      在這章的多數例子里, 參數是通過工廠方法引入的(例如 CrayonBox::getColor(‘紅色’);)。《GoF》中則稱為“參數化工廠”(parameterized factory),它是PHP網頁設計中典型的工廠方法。

      你現在已經了解工廠模式了, 它是一種代碼中建立新對象的管理技術。 你可以看到工廠模式是可以把復雜對象的建立集中起來,甚至用不同的類代替不同的對象。最后,工廠模式支持OOP技術中的多態也是很重要的。

      function TestGetRgbRed() {
      $red =& new Color(255,0,0);
      $this->assertEqual(‘#FF0000’, $red->getRgb());
      }

      分享:《PHP設計模式介紹》第一章 編程慣用法
      學習一門新的語言意味著要采用新的慣用法。這章將介紹或者可能重新強調一些慣用法。你會發現這些慣用法在你要在代碼中實現設計模式時候是非常有用的。 在這里總結的許多編程慣用法都是很值得

      共8頁上一頁12345678下一頁
      來源:模板無憂//所屬分類:PHP教程/更新時間:2008-08-22
      相關PHP教程