觀察者模式: 觀察者模式(Observer Pattern):定義對象間的一種一對多依賴關係,使得每當一個對象狀態發生改變時,其相關依賴對象皆得到通知並被自動更新。觀察者模式又叫做發佈-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監聽器(Source/ ...
觀察者模式:
觀察者模式(Observer Pattern):定義對象間的一種一對多依賴關係,使得每當一個對象狀態發生改變時,其相關依賴對象皆得到通知並被自動更新。觀察者模式又叫做發佈-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監聽器(Source/Listener)模式或從屬者(Dependents)模式。
觀察者模式是一種對象行為型模式。
模式動機
建立一種對象與對象之間的依賴關係,一個對象發生改變時將自動通知其他對象,其他對象將相應做出反應。在此,發生改變的對象稱為觀察目標,而被通知的對象稱為觀察者,一個觀察目標可以對應多個觀察者,而且這些觀察者之間沒有相互聯繫,可以根據需要增加和刪除觀察者,使得系統更易於擴展,這就是觀察者模式的模式動機。
觀察者模式包含如下角色:
Subject: 目標
ConcreteSubject: 具體目標
Observer: 觀察者
ConcreteObserver: 具體觀察者
UML類圖:
適用性:
當一個抽象模型有兩個方面, 其中一個方面依賴於另一方面。將這二者封裝在獨立的對象中以使它們可以各自獨立地改變和復用。
當對一個對象的改變需要同時改變其它對象, 而不知道具體有多少對象有待改變。
當一個對象必須通知其它對象,而它又不能假定其它對象是誰。換言之, 你不希望這些對象是緊密耦合的
//代碼實現
<?php header("Content-type:text/html;Charset=utf-8"); //目標介面,定義觀察目標要實現的方法 abstract class Subject{ abstract function attach(Observer $observer); //添加觀察者 abstract function detach(Observer $observer); //去除觀察者 abstract function notify(); //滿足條件時通知所有觀察者修改 abstract function condition($num); //發起通知的條件 } //具體觀察目標 class ConcreteSubject extends Subject{ private $observers = array(); //添加觀察者 function attach(Observer $observer){ $this->observers[] = $observer; } //移除觀察者 function detach(Observer $observer){ $key=array_search($observer, $this->observers); if($key !== false){ //註意不要寫成!=,表達式0!=flase為flase unset($this->observers[$key]); } } //通知所有所有觀察者修改 function notify(){ foreach($this->observers as $observer){ $observer->update(); } } //發起通知的條件 function condition($num){ if($num>100){ $this->notify(); } } } //抽象觀察者介面,定義所有觀察者共同具有的屬性——執行修改 abstract class Observer{ abstract function update(); } //具體觀察者類,實現抽象觀察者介面 class ConcreteObserverA extends Observer{ function update(){ echo "A報告:敵軍超過一百人了,快撤!<br>"; } //其他函數 function eat(){ echo "A在吃飯"; } } class ConcreteObserverB extends Observer{ function update(){ echo "B報告:敵軍超過一百人了,快撤!<br>"; } //其他函數 function sleep(){ echo "B在睡覺"; } } //測試 $observerA = new ConcreteObserverA(); $observerB = new ConcreteObserverB(); $concreteSubject = new ConcreteSubject(); $concreteSubject->attach($observerA); //添加觀察者A $concreteSubject->detach($observerA); //去除觀察者A $concreteSubject->attach($observerA); $concreteSubject->attach($observerB); $concreteSubject->condition(1000); ?>