另外,如果你不喜歡該模式下對象與對象之間的連接方式,你可以更改update()函數讓它來發(fā)送一個信息(類似于本例中的錯誤信息數組或者幾個信息對象)來避免引用自己。
這里是一個全新的ErrorHandler,不僅做了最新的修改并且還包含detach()函數:
class ErrorHandler { var $_observers=array(); var $_error_info; function attach(&$observer) { $this->_observers[] =& $observer; } function detach(&$observer) { foreach(array_keys($this->_observers) as $key) { if ($this->_observers[$key] === $observer) { unset($this->_observers[$key]); return; } } } function notify() { foreach(array_keys($this->_observers) as $key) { $observer =& $this->_observers[$key]; $observer->update($this); } } function getState() { return $this->_error_info; } function setState($info) { $this->_error_info = $info; $this->notify(); } }
你現在已經擁有了觀測模式下的一個完整工具。
現在,回到本章的原始目標中,讓我們看看如何在一個真正的PHP腳本中應用ErrorHandler。為了在一個PHP應用中包含觀測者,你必須實例化ErrorHandler類,并確認函數set_error_handler()使用完全相同的參數。這聽起來就像最近的一個問題:單件模式。
讓我們作一個Factory()函數,它是一個簡單的PHP函數,可以返回ErrorHandler的單態(tài)實例。
function &getErrorHandlerInstance() { static $instance = array(); if (!$instance) $instance[0] =& new ErrorHandler(); return $instance[0]; }
現在,讓我們寫一個錯誤記錄句柄功能來獲取單態(tài)ErrorHandler,改變它的狀態(tài)來反映錯誤,并且通知“觀測者”。
function observer_error_handler( $errno, $errstr, $errfile, $errline, $errcontext) { $eh =& getErrorHandlerInstance(); $eh->setState(array( ‘number’ => $errno
,’msg’ => $errstr ,’file’ => $errfile ,’line’ => $errline ,’context’ => $errcontext )); }
也許你會注意到這里并沒有ErrorHandler::notify()函數。為什么呢?因為ErrorHandler不論何時,只要狀態(tài)一改變就會自動發(fā)出通知。
class ErrorHandler { // ... function setState($info) { $this->_error_info = $info; $this->notify(); } }
這種“默認通知”的方法,有利有弊。但先進之處在于客戶端代碼不需要包含通知的觸發(fā)代碼。
當然,如果主體對象的狀態(tài)有好幾處變化,所有的變動都對應不同的函數,你就可以選擇讓客體代碼強制調用notify()函數。
自從你能正確使用這些輔助工具后,你給ErrorHandler添加的另一種類型的記錄方式就會變得相當的容易?你現在只需要擁有向系統(tǒng)中寫日志的權限。稍微查一下PHP手冊(http://www.php.net/syslog),你就可以找到一些非常有用的函數來建立日志系統(tǒng)。這些可以很容易的被封裝到一個新的類里,以便和ErrorHandler聯(lián)合使用。
class SyslogErrorLogger { function SyslogErrorLogger($msg) { define_syslog_variables(); openlog($msg, LOG_ODELAY, LOG_USER); }
function log($msg) { syslog(LOG_WARNING, $msg); }
function update(&$error_handler) { $error = $error_handler->getState(); $this->log($error[‘msg’]); } }
注:錯誤日志的用處 日志是非常有用的――如果有人使用它們的話。但是,如果沒有人使用日志,那么記錄日志的代碼就是一堆無用的代碼 如果想知道更詳細的評價,請查看 http://www.lastcraft.com/blog/index.php?p=4
結論
觀測模式是非常有用的。這里的例子是完全靜態(tài)的--觀測者可以在腳本的初始化階段被配置且被生成。要想展示觀測模式的靈活性,最好是在一個更加動態(tài)的應用中--你需要根據腳本中的其他事情來添加或刪除觀測者。以常見的“生存時間”或者說該PHP腳本的允許執(zhí)行時間打個比方,當同一個腳本在不同的情況下執(zhí)行時,就可以根據不同的觀測者分別配置,而不需要動態(tài)改變一個腳本的流程。這就和通過延長腳本執(zhí)行時間的PHP-GTK庫有很大不同。
下文:《PHP設計模式介紹》第十章 規(guī)范模式
本文鏈接:http://www.95time.cn/tech/program/2008/6029.asp
出處:phpchina
責任編輯:bluehearts
上一頁 php設計模式介紹之觀測模式 [3] 下一頁
◎進入論壇網絡編程版塊參加討論
|