《PHP設(shè)計(jì)模式介紹》第六章 偽對(duì)象模式(2)_PHP教程
推薦:《PHP設(shè)計(jì)模式介紹》第五章 注冊(cè)模式我們通常認(rèn)為避免使用全局變量是一種好的選擇,因此,對(duì)象經(jīng)常被作為參數(shù)從一段代碼傳遞到另一段。但是傳遞實(shí)例的一個(gè)問(wèn)題就是對(duì)象有時(shí)候不知道將要傳遞給誰(shuí)——?經(jīng)過(guò)一個(gè)函數(shù)后才被傳
具備了這個(gè)思想,讓我們看看如何封裝$_SESSION之類的全局變量。
|
class Session { |
你也許注意到了構(gòu)造函數(shù)調(diào)用了Session::init()方法。為什么這個(gè)方法不是構(gòu)造函數(shù)的一部分呢?這樣分開的好處是你能靜態(tài)調(diào)用它并確保session已經(jīng)開始。下面是一個(gè)如何使用該類的例子。
| Session::init(); $page =& new PageDirector(new Session); |
大部分測(cè)試方面的文獻(xiàn)很推崇偽對(duì)象并建議你親自寫一個(gè)。如果你打算那樣做,開始測(cè)試時(shí)你就只需要充實(shí)那些你需要的方法就可以了。譬如,一個(gè)用于處理代碼的ServerStub的Session類很可能是這樣的:
| class MyMockSessionUser1 { function isValid($key) { return (‘user_id’ == $key) ? true : false; } function get($key) { if (‘user_id’ == $key) { return 1; } } } |
幸運(yùn)的是,你可以用SimpleTest來(lái)避免那些易范的錯(cuò)誤。Mock::generate()方法允許你創(chuàng)建一個(gè)類來(lái)實(shí)例化或動(dòng)態(tài)地配置你想要的結(jié)果。
注:偽對(duì)象技術(shù)
SimpleTest所使用的方法僅是偽對(duì)象的多種用法之一。偽對(duì)象的代碼傳遞是另一種。隨著PHP5的到來(lái),你也許能看到偽對(duì)象以對(duì)象中的__call()方法來(lái)執(zhí)行。
以下是如何用SimpleTest生成的偽對(duì)象來(lái)測(cè)試并重構(gòu)MyMockSessionUser1類(如上例中)。
| Mock::Generate(‘Session’); class PageDirectorTestCase extends UnitTestCase { function testSomethingWhichUsesSession() { $session =& new MockSession($this); $session->setReturnValue(‘isValid’, true); $session->setReturnValue(‘get’, 1); // ... } } |
更進(jìn)一步說(shuō),你能隨心所欲的設(shè)置何種方法被調(diào)用以及調(diào)用多少次。你甚至可以驗(yàn)證那些根本不該被調(diào)用的方法。
下面是一個(gè)擴(kuò)展型的測(cè)試,它用來(lái)建立和驗(yàn)證那些復(fù)雜的設(shè)計(jì)。
| class PageDirectorTestCase extends UnitTestCase { function testSomethingWhichUsesSession() { $session =& new MockSession($this); $session->setReturnValue(‘isValid’, true); $session->setReturnValue(‘get’, 1); $session->expectOnce(‘isValid’, array(‘user_id’)); $session->expectOnce(‘get’, array(‘user_id’)); $session->expectNever(‘set’); // the actual code which uses $session $session->tally(); } } |
使用偽對(duì)象的原因很多,方法也多樣化。但在我們繼續(xù)前,讓我們把另外的一些類加入進(jìn)來(lái),使其來(lái)龍去脈更加清楚。
接下來(lái)的一部分是重構(gòu)已有腳本,創(chuàng)建一個(gè)用于檢查用戶是否有相應(yīng)權(quán)限的名為UserLogin的類。
| class UserLogin { var $_valid=true; var $_id; var $_name; function UserLogin($name) { switch (strtolower($name)) { case ‘admin’: $this->_id = 1; $this->_name = ‘admin’; break; default: trigger_error(“Bad user name ‘$name’”); $this->_valid=false; } } function name() { if ($this->_valid) return $this->_name; } function Validate($user_name, $password) { if (‘admin’ == strtolower($user_name) && ‘secret’ == $password) { return true; } return false; } } |
最后一部分是創(chuàng)建響應(yīng)。為了最終在瀏覽器中顯示,我們必須處理那不斷增長(zhǎng)的HTML內(nèi)容,如果必要的話我們也會(huì)討論HTTP重定向。(你也可以執(zhí)行其他的http頭的操作——這樣說(shuō)是為了能構(gòu)隱藏它——在一個(gè)成熟的做法中,但這里使用的是一段更簡(jiǎn)單的代碼,是為了使例子容易理解與關(guān)注。)
| class Response { var $_head=’’; var $_body=’’; function addHead($content) { $this->_head .= $content; } function addBody($content) { $this->_body .= $content; } function display() { echo $this->fetch(); } function fetch() { return ‘<html>’ .’<head>’.$this->_head.’</head>’ .’<body>’.$this->_body.’</body>’ .’</html>’; } function redirect($url, $exit=true) { header(‘Location: ‘.$url); if ($exit) exit; } } |
給出了這些模塊后,也是時(shí)候?qū)⑦@些新開發(fā)的、已測(cè)試的組件聚合到一個(gè)頁(yè)面中了。讓我們寫一個(gè)最終的類來(lái)協(xié)調(diào)這個(gè)頁(yè)面的所以行為,取個(gè)合適的名字PageDirector。類PageDirector具有一個(gè)很簡(jiǎn)單的運(yùn)用程序接口:你在實(shí)例化后可以用調(diào)用它的run()方法。
分享:《PHP設(shè)計(jì)模式介紹》第四章 單件模式幾乎所有面向?qū)ο蟮某绦蛑校傆幸粌蓚(gè)資源被創(chuàng)建出來(lái),在程序應(yīng)用中持續(xù)被共享使用。例如,這樣的一個(gè)資源,在一個(gè)電子商務(wù)程序的數(shù)據(jù)庫(kù)連接中使用:這個(gè)連接在應(yīng)用程序啟動(dòng)時(shí)初始化,程序于是
- PHPNOW安裝Memcached擴(kuò)展方法詳解
- php記錄頁(yè)面代碼執(zhí)行時(shí)間
- PHP中獎(jiǎng)概率的抽獎(jiǎng)算法程序代碼
- apache設(shè)置靜態(tài)文件緩存方法介紹
- php對(duì)圖像的各種處理函數(shù)代碼小結(jié)
- PHP 關(guān)于訪問(wèn)控制的和運(yùn)算符優(yōu)先級(jí)介紹
- 關(guān)于PHP語(yǔ)言構(gòu)造器介紹
- php/js獲取客戶端mac地址的實(shí)現(xiàn)代碼
- php5.5新數(shù)組函數(shù)array_column使用
- PHP preg_match的匹配多國(guó)語(yǔ)言的技巧
- php 中序列化和json使用介紹
- php采集文章中的圖片獲取替換到本地
- 相關(guān)鏈接:
- 教程說(shuō)明:
PHP教程-《PHP設(shè)計(jì)模式介紹》第六章 偽對(duì)象模式(2)
。