有了合適而正確的觀測者,我們就可以在觀測模式下,從函數attach()開始繼續(xù)測試ErrorHandler類。
class Observer { function update() { die(‘abstract method’); } } Mock::Generate(‘Observer’);
class ErrorHandlerTestCase extends UnitTestCase { function TestAttach() { $eh =& new ErrorHandler; $observer =& new MockObserver($this); $observer->expectOnce( ‘update’ ,array(‘*’)); // array(&$eh)
$eh->attach($observer); $eh->notify(); $observer->tally();
} function TestDetach() { /* ... */ } }
在這次測試中,一個簡單的觀測類被創(chuàng)建出來,作為所有觀測者的接口。為了測試函數attach(),一個基于這個觀測類的偽模式被創(chuàng)建出來,并且和ErrorHandler測試實例關聯在一起。然后,當公共函數notify()被調用時,偽模式將證實update()函數曾經被調用過。
請注意剛才提及的的在模擬觀測中所創(chuàng)建的函數array(&$eh)中的參數。在理想狀態(tài)中,那個測試應該可以通過的。然而,由于PHP語言的限制,這將產生一個致命錯誤:“Nesting Level Too Deep――循環(huán)依賴?”。為了避免出現那樣的問題,代碼中必須使用簡單測試下“Wild Card”功能,以便允許所有參數都能像預期的那樣傳遞。
? Nesting Level Too Deep
因為ErrorHandler在數組$_observer中包含涉及到模擬觀測的參數,本來預期是要將它傳遞給模擬觀測的。所以,PHP產生一個“Nesting Level Too Deep”錯誤。而循環(huán)依賴就像一個初級的PHP問題,甚至可以在一個簡單的PHP環(huán)境中發(fā)現它。(請參考http://bugs.php.net/bug.php?id=31449.)
ErrorHandler開始應該像下面這樣構造:
class ErrorHandler { var $_observers=array(); function attach(&$observer) { $this->_observers[] =& $observer; }
function notify() { foreach(array_keys($this->_observers) as $key) { $observer =& $this->_observers[$key]; $observer->update($this); } }
根據上面的代碼,你必須在每一個具體的觀測者中添加一個update()函數。在每個實例中,update()函數需要知道如何從被觀測者ErrorHandler類中獲取信息,進而執(zhí)行自身的相應功能。這里是添加的代碼。
class FileErrorLogger { var $_fh; function FileErrorLogger($file_handle) { $this->_fh = $file_handle; } function write($msg) { fwrite($this->_fh, date(‘Y-m-d H:i:s: ‘).$msg); } function update(&$error_handler) { $error = $error_handler->getState(); $this->write($error[‘msg’]); } }
class EmailErrorLogger { var $_addr; var $_subject; function EmailErrorLogger($addr, $subject=’Application Error Message’) { $this->_addr = $addr; $this->_subject = $subject; } function mail($msg) { mail($this->_addr ,$this->_subject ,date(‘Y-m-d H:i:s: ‘).$msg); } function update(&$error_handler) { $error = $error_handler->getState(); $this->mail($error[‘msg’]); } }
上面兩個update()函數中的每一個,都需要將ErrorHandler作為參數,以便從中獲得錯誤信息,然后調用一個內部函數,來處理這個錯誤。每個update()函數通過ErrorHandler中的getState()函數來獲取信息。那個函數以getState()命名是為了在GoF模式中,保持模式的整體和諧性。但是,如果將這個函數命名為getError()或者getErrorInfo()就更加合適,因為這兩個名字更加貼近這個函數的功能。
出處:phpchina
責任編輯:bluehearts
上一頁 php設計模式介紹之觀測模式 [2] 下一頁 php設計模式介紹之觀測模式 [4]
◎進入論壇網絡編程版塊參加討論
|