《PHP設(shè)計(jì)模式介紹》第九章 觀測模式(2)_PHP教程
推薦:《PHP設(shè)計(jì)模式介紹》第八章 迭代器模式類中的面向?qū)ο缶幊谭庋b應(yīng)用邏輯。類,就是實(shí)例化的對(duì)象,每個(gè)單獨(dú)的對(duì)象都有一個(gè)特定的身份和狀態(tài)。單獨(dú)的對(duì)象是一種組織代碼的有用方法,但通常你會(huì)處理一組對(duì)象或者集合。 屬性來自 SQL 查
ErrorHandler開始應(yīng)該像下面這樣構(gòu)造:
classErrorHandler{
var$_observers=array();
functionattach(&$observer){
$this->_observers[]=&$observer;
}
functionnotify(){
foreach(array_keys($this->_observers)as$key){
$observer=&$this->_observers[$key];
$observer->update($this);
}
}
根據(jù)上面的代碼,你必須在每一個(gè)具體的觀測者中添加一個(gè)update()函數(shù)。在每個(gè)實(shí)例中,update()函數(shù)需要知道如何從被觀測者ErrorHandler類中獲取信息,進(jìn)而執(zhí)行自身的相應(yīng)功能。這里是添加的代碼。
classFileErrorLogger{
var$_fh;
functionFileErrorLogger($file_handle){
$this->_fh=$file_handle;
}
functionwrite($msg){
fwrite($this->_fh,date(‘Y-m-dH:i:s:‘).$msg);
}
functionupdate(&$error_handler){
$error=$error_handler->getState();
$this->write($error[‘msg’]);
}
}
classEmailErrorLogger{
var$_addr;
var$_subject;
functionEmailErrorLogger($addr,
$subject=’ApplicationErrorMessage’){
$this->_addr=$addr;
$this->_subject=$subject;
}
functionmail($msg){
mail($this->_addr
,$this->_subject
,date(‘Y-m-dH:i:s:‘).$msg);
}
functionupdate(&$error_handler){
$error=$error_handler->getState();
$this->mail($error[‘msg’]);
}
}
另外,如果你不喜歡該模式下對(duì)象與對(duì)象之間的連接方式,你可以更改update()函數(shù)讓它來發(fā)送一個(gè)信息(類似于本例中的錯(cuò)誤信息數(shù)組或者幾個(gè)信息對(duì)象)來避免引用自己。
這里是一個(gè)全新的ErrorHandler,不僅做了最新的修改并且還包含detach()函數(shù):
classErrorHandler{
var$_observers=array();
var$_error_info;
functionattach(&$observer){
$this->_observers[]=&$observer;
}
functiondetach(&$observer){
foreach(array_keys($this->_observers)as$key){
if($this->_observers[$key]===$observer){
unset($this->_observers[$key]);
return;
}
}
}
functionnotify(){
foreach(array_keys($this->_observers)as$key){
$observer=&$this->_observers[$key];
$observer->update($this);
}
}
functiongetState(){
return$this->_error_info;
}
functionsetState($info){
$this->_error_info=$info;
$this->notify();
}
}
你現(xiàn)在已經(jīng)擁有了觀測模式下的一個(gè)完整工具。
現(xiàn)在,回到本章的原始目標(biāo)中,讓我們看看如何在一個(gè)真正的PHP腳本中應(yīng)用ErrorHandler。為了在一個(gè)PHP應(yīng)用中包含觀測者,你必須實(shí)例化ErrorHandler類,并確認(rèn)函數(shù)set_error_handler()使用完全相同的參數(shù)。這聽起來就像最近的一個(gè)問題:單件模式。
讓我們作一個(gè)Factory()函數(shù),它是一個(gè)簡單的PHP函數(shù),可以返回ErrorHandler的單態(tài)實(shí)例。
function&getErrorHandlerInstance(){
static$instance=array();
if(!$instance)$instance[0]=&newErrorHandler();
return$instance[0];
}
現(xiàn)在,讓我們寫一個(gè)錯(cuò)誤記錄句柄功能來獲取單態(tài)ErrorHandler,改變它的狀態(tài)來反映錯(cuò)誤,并且通知“觀測者”。
functionobserver_error_handler(
$errno,$errstr,$errfile,$errline,$errcontext){
$eh=&getErrorHandlerInstance();
$eh->setState(array(
‘number’=>$errno
,’msg’=>$errstr
,’file’=>$errfile
,’line’=>$errline
,’context’=>$errcontext
));
}
也許你會(huì)注意到這里并沒有ErrorHandler::notify()函數(shù)。為什么呢?因?yàn)镋rrorHandler不論何時(shí),只要狀態(tài)一改變就會(huì)自動(dòng)發(fā)出通知。
classErrorHandler{
//...
functionsetState($info){
$this->_error_info=$info;
$this->notify();
}
}
這種“默認(rèn)通知”的方法,有利有弊。但先進(jìn)之處在于客戶端代碼不需要包含通知的觸發(fā)代碼。
當(dāng)然,如果主體對(duì)象的狀態(tài)有好幾處變化,所有的變動(dòng)都對(duì)應(yīng)不同的函數(shù),你就可以選擇讓客體代碼強(qiáng)制調(diào)用notify()函數(shù)。
自從你能正確使用這些輔助工具后,你給ErrorHandler添加的另一種類型的記錄方式就會(huì)變得相當(dāng)?shù)娜菀�?你現(xiàn)在只需要擁有向系統(tǒng)中寫日志的權(quán)限。稍微查一下PHP手冊(cè)(http://www.php.net/syslog),你就可以找到一些非常有用的函數(shù)來建立日志系統(tǒng)。這些可以很容易的被封裝到一個(gè)新的類里,以便和ErrorHandler聯(lián)合使用。
classSyslogErrorLogger{
functionSyslogErrorLogger($msg){define_syslog_variables();openlog($msg,LOG_ODELAY,LOG_USER);
}
functionlog($msg){
syslog(LOG_WARNING,$msg);
}
functionupdate(&$error_handler){
$error=$error_handler->getState();
$this->log($error[‘msg’]);
}
}
注:錯(cuò)誤日志的用處
日志是非常有用的――如果有人使用它們的話。但是,如果沒有人使用日志,那么記錄日志的代碼就是一堆無用的代碼
如果想知道更詳細(xì)的評(píng)價(jià),請(qǐng)查看
http://www.lastcraft.com/blog/index.php?p=4
結(jié)論
觀測模式是非常有用的。這里的例子是完全靜態(tài)的--觀測者可以在腳本的初始化階段被配置且被生成。要想展示觀測模式的靈活性,最好是在一個(gè)更加動(dòng)態(tài)的應(yīng)用中--你需要根據(jù)腳本中的其他事情來添加或刪除觀測者。以常見的“生存時(shí)間”或者說該P(yáng)HP腳本的允許執(zhí)行時(shí)間打個(gè)比方,當(dāng)同一個(gè)腳本在不同的情況下執(zhí)行時(shí),就可以根據(jù)不同的觀測者分別配置,而不需要?jiǎng)討B(tài)改變一個(gè)腳本的流程。這就和通過延長腳本執(zhí)行時(shí)間的PHP-GTK庫有很大不同。
分享:《PHP設(shè)計(jì)模式介紹》第七章 策略模式在編寫面向?qū)ο蟮拇a的時(shí),有些時(shí)候你需要一個(gè)能夠自己根據(jù)不同的條件來引入不同的操作對(duì)象實(shí)例。例如,一個(gè)菜單功能能夠根據(jù)用戶的“皮膚”首選項(xiàng)來決定是否采用水平的還是垂直的排
- PHPNOW安裝Memcached擴(kuò)展方法詳解
- php記錄頁面代碼執(zhí)行時(shí)間
- PHP中獎(jiǎng)概率的抽獎(jiǎng)算法程序代碼
- apache設(shè)置靜態(tài)文件緩存方法介紹
- php對(duì)圖像的各種處理函數(shù)代碼小結(jié)
- PHP 關(guān)于訪問控制的和運(yùn)算符優(yōu)先級(jí)介紹
- 關(guān)于PHP語言構(gòu)造器介紹
- php/js獲取客戶端mac地址的實(shí)現(xiàn)代碼
- php5.5新數(shù)組函數(shù)array_column使用
- PHP preg_match的匹配多國語言的技巧
- php 中序列化和json使用介紹
- php采集文章中的圖片獲取替換到本地
- 相關(guān)鏈接:
- 教程說明:
PHP教程-《PHP設(shè)計(jì)模式介紹》第九章 觀測模式(2)
。