今天來介紹乙個很有用的設計模式,「觀察者模式」,顧名思義,既然有「觀察者」, 那麼一定就有「被觀察者」,從這個層面可以理解到,在這個設計模式中有兩個物件, 乙個是主體物件,乙個是客體物件,在實際的**實現上實際是「被觀察者」主動通知了「觀察者」。「被觀察者」是主體物件,現在看不懂沒關係,把下面的**抄幾遍就懂了。
php 提供了兩個內建介面來幫助實現「觀察者模式」, 其中「被觀察者」需要實現splsubject
介面,「觀察者」需要實現sploberver
。
來看乙個例子:
<?php
class plugina implements splobserver
}class pluginb implements splobserver
}class user implements splsubject
public function attach(\splobserver $observer)
public function detach(\splobserver $observer)
}public function notify()
}}//-- 例項化主體物件
$user = new user();
//-- end
//-- 註冊外掛程式
$plugins = [
new plugina(),
new pluginb(),
];foreach ($plugins as $plugin)
//-- end
//-- 執行主體的業務**
$user->register('shanhuhai', '123456');
將以上**儲存即可執行。
以上**模擬了乙個呼叫註冊方法register
時,通知相關外掛程式執行相應任務的機制。它使用觀察者模式實現了外掛程式的機制。
外掛程式物件plugina
和pluginb
的例項就是「觀察者」,user
類的例項$user
是「被觀察者」,「觀察者」需要通過attach
方法註冊到「被關觀察者」 上,
當register
方法被時,user
會通過notify
方法來通知所有的外掛程式,並將主體物件即被觀察者傳遞給外掛程式。
這裡僅僅是通過最簡單的**展示了什麼是觀察者模式,如果想實現外掛程式,我們應該能傳遞更多的資訊給外掛程式,比如我們想在外掛程式中針對主體物件的發生不同事件(不同的方法被呼叫)做不同的處理,我們可能需要「事件」的概念,你知道如何實現麼?
在實際的業務中,觀察者應該對不同的情況做出不同的發應,這個其實很簡單,我們加乙個給主體物件加乙個event
的屬性就ok了。
<?php
/** * 支援了事件的版本
*/class plugina implements splobserver
}}class pluginb implements splobserver
if($subject->event == 'login')
}}class user implements splsubject
public function login($name, $password)
public function attach(\splobserver $observer)
public function detach(\splobserver $observer)
}public function notify()
}}//-- 例項化主體物件
$user = new user();
//-- end
//-- 註冊外掛程式
$plugins = [
new plugina(),
new pluginb(),
];foreach ($plugins as $plugin)
//-- end
//-- 執行主體的業務**
$user->register('shanhuhai', '123456');
$user->login('shanhuhai', '123456');
完成了這個之後你會發現乙個問題,目前來看我必須將所有的外掛程式例項化後才能註冊到主體物件中,那麼問題來了,如果乙個外掛程式,只處理部分事件,那麼如果在整個程式處理過程中這個事件沒有被觸發,那麼這個外掛程式的例項化是不是浪費了?
外掛程式可以根據不同的事件來做不同的業務處理,基本上很簡單,我們直接通過主體物件攜帶事件名稱即可。
下面我們要實現的是,只有在知道具體事件後才去例項化繫結了此事件的外掛程式。
下面是具體的實現:
<?php
/** * author: shanhuhai
* date: 2017/8/28 21:26
* mail: [email protected]
*/class plugina implements splobserver
}}class pluginb implements splobserver
if($subject->event == 'login')
}}class observer implements splobserver }}
public function update(\splsubject $subject) }}
}class user implements splsubject
public function login($name, $password)
public function attach(\splobserver $observer)
public function detach(\splobserver $observer)
public function notify()
}//-- 例項化主體物件
$user = new user();
//-- end
//-- 配置外掛程式
$config = [
'plugina' => ['register' ],
'pluginb' => ['register', 'login'],
];//-- end
//-- 註冊外掛程式
$observer = new observer($config);
$user->attach($observer);
//-- end
//-- 執行主體的業務**
$user->register('shanhuhai', '123456');
$user->login('shanhuhai', '123456');
其實觀察者模式還叫「發布/訂閱模式」, 這跟訊息佇列中說的「發布/訂閱」基本上是乙個意思,我們在$config
的配置說明了訂閱關係,哪個外掛程式訂閱哪個事件,當被訂閱的事件發生時這個外掛程式就會收到訊息。比如plugina
訂閱了register
事件,當主體物件中 指定的event
等於register
時,plugina
將會被例項化並接收到主體物件傳過來的資料。
在實際應用情況中,外掛程式應該在乙個特定目錄中,每個外掛程式是乙個檔案,以上機制想要應用到你的專案中,還要根據實際情況做相應修改。
php設計模式之 觀察者模式
觀察者模式 observer 當乙個物件狀態發生改變時,依賴它的物件全部收到通知,並自動更新。抽象被觀察者 abstract class eventgenerator 通知所有觀察者 public function notify 具體被觀察者class event extends eventgene...
PHP 設計模式之觀察者模式
介紹現在有兩派,有的人建議使用設計模式,有的人不建議使用設計模式!這就向寫文章一樣,有的人喜歡文章按照套路走,比如敘事性質的文章,時間,地點,人物,事件。而有的人喜歡寫雜文或者散文,有的人喜歡寫詩詞!很多時候,我看設計模式的時候,有些設計模式只是吻合我的 習慣。但是你硬去套它,那麼反而適得其反。很多...
php 設計模式之觀察者模式
觀察者模式 1.抽象事件發生類 abstract class eventgenerator 對 所有 觀察者 進行 事件 通知 function notify 2.宣告具體事件類 class event extends eventgenerator 3.宣告 乙個 觀察者 介面 inte ce ob...