觀察者模式有時也被稱作發(fā)布/訂閱模式病涨,該模式用于為對象實現(xiàn)發(fā)布/訂閱功能:一旦主體對象狀態(tài)發(fā)生改變,與之關(guān)聯(lián)的觀察者對象會收到通知宫峦,并進(jìn)行相應(yīng)操作辕录。
將一個系統(tǒng)分割成一個一些類相互協(xié)作的類有一個不好的副作用,那就是需要維護(hù)相關(guān)對象間的一致性缓熟。我們不希望為了維持一致性而使各類緊密耦合累魔,這樣會給維護(hù)、擴(kuò)展和重用都帶來不便够滑。觀察者就是解決這類的耦合關(guān)系的垦写。
消息隊列系統(tǒng)、事件都使用了觀察者模式彰触。
業(yè)務(wù)場景:
哈票以購票為核心業(yè)務(wù)(此模式不限于該業(yè)務(wù))梯投,但圍繞購票會產(chǎn)生不同的其他邏輯,如:
1渴析、購票后記錄文本日志
2晚伙、購票后記錄數(shù)據(jù)庫日志
3、購票后發(fā)送短信
4俭茧、購票送抵扣卷咆疗、兌換卷、積分
5母债、其他各類活動等
傳統(tǒng)解決方案:
在購票邏輯等類內(nèi)部增加相關(guān)代碼午磁,完成各種邏輯。
觀察者模式典型實現(xiàn)方式:
1毡们、定義2個接口:觀察者(通知)接口迅皇、被觀察者(主題)接口
2、定義2個類衙熔,觀察者對象實現(xiàn)觀察者接口登颓、主題類實現(xiàn)被觀者接口
3、主題類注冊自己需要通知的觀察者
4红氯、主題類某個業(yè)務(wù)邏輯發(fā)生時通知觀察者對象框咙,每個觀察者執(zhí)行自己的業(yè)務(wù)邏輯咕痛。
示例代碼:
觀察者接口:
interface TicketObserver {
//得到通知后調(diào)用的方法
public function onBuyTicketOver($sender, $args);
}
被觀察者接口:
interface TicketObservable {
//提供注冊觀察者方法
public function addObserver($observer);
}
觀察者:
//短信通知
class MSM implements ITicketObserver {
public function onBuyTicketOver($sender, $ticket) {
echo "短信通知";
}
}
//push通知
class Push implements ITicketObserver {
public function onBuyTicketOver($sender, $ticket) {
echo "push通知"喇嘱;
}
}
被觀察者:
class Ticket implements TicketObservable {
private $_comsumer;
private $_observers = array (); //觀察者
//購票流程
public function buyTicket($ticket) {
// TODO 購票邏輯
//循環(huán)通知茉贡,調(diào)用其onBuyTicketOver實現(xiàn)不同業(yè)務(wù)邏輯
foreach ( $this->_observers as $obs )
$obs->onBuyTicketOver ( $this->_comsumer, $ticket );
}
//添加通知
public function addObserver($observer) {
$this->_observers [] = $observer;
}
}