一個(gè)"演員"(被觀察者),一群"觀眾"(觀察者),一臺"攝影機(jī)"(記錄容器)
【觀察者模式中主要角色】
1.抽象主題(Subject)角色:主題角色將所有對觀察者對象的引用保存在一個(gè)集合中,每個(gè)主題可以有任意多個(gè)觀察者。 抽象主題提供了增加和刪除觀察者對象的接口。
2.抽象觀察者(Observer)角色:為所有的具體觀察者定義一個(gè)接口,在觀察的主題發(fā)生改變時(shí)更新自己。
3.具體主題(ConcreteSubject)角色:存儲相關(guān)狀態(tài)到具體觀察者對象,當(dāng)具體主題的內(nèi)部狀態(tài)改變時(shí),給所有登記過的觀察者發(fā)出通知。具體主題角色通常用一個(gè)具體子類實(shí)現(xiàn)。
4.具體觀察者(ConcretedObserver)角色:存儲一個(gè)具體主題對象,存儲相關(guān)狀態(tài),實(shí)現(xiàn)抽象觀察者角色所要求的更新接口,以使得其自身狀態(tài)和主題的狀態(tài)保持一致。
【使用場景】
假設(shè)項(xiàng)目經(jīng)理讓我們寫了一個(gè)登陸接口,咔咔擦擦寫完了
第二天讓我們加入統(tǒng)計(jì)登陸次數(shù),然后在后面加代碼第三天讓我們判斷登陸地區(qū),又在后面加代碼第四天讓我們在用戶登陸后推送活動,再再后面加代碼第N天,這個(gè)接口已經(jīng)雜亂到?jīng)]人想維護(hù)了
我們需要讓項(xiàng)目保持高內(nèi)聚低耦合,就可以用到觀察者模式(非必須,看需求)
【觀察者模式與其它模式】
1.【中介者模式】(Mediator):通過封裝復(fù)雜的更新語義,ChangeManager充當(dāng)目標(biāo)和觀察者之間的中介者。
2.【單例模式】(singleton模式):ChangeManager可使用Singleton模式來保證它是唯一的并且是可全局訪問的。
接口示例
// 主題接口 interface Subject{ public function register(Observer $observer); public function notify(); } // 觀察者接口 interface Observer{ public function watch(); }
Subject就是被觀察者,Observer就是觀眾,也就是觀察者
被觀察者
// 被觀察者 class Action implements Subject{ public $_observers=array(); public function register(Observer $observer){ $this->_observers[]=$observer; } public function notify(){ foreach ($this->_observers as $observer) { $observer->watch(); } } }
Action實(shí)現(xiàn)了被觀察者接口,他現(xiàn)在就是被觀察者,再定義一個(gè)$_observers數(shù)組,他就是記錄觀眾的容器了。
首先實(shí)現(xiàn)register方法,用它傳入一個(gè)觀察者,然后塞到數(shù)組里,再實(shí)現(xiàn)notify()方法,它會遍歷容器數(shù)組,執(zhí)行每個(gè)觀察者的watch()方法。
觀察者
// 觀察者 class Cat implements Observer{ public function watch(){ echo "Cat watches TVhr/>"; } } class Dog implements Observer{ public function watch(){ echo "Dog watches TVhr/>"; } } class People implements Observer{ public function watch(){ echo "People watches TVhr/>"; } }
這里定義了三個(gè)觀察者,全都實(shí)現(xiàn)了Observer接口,前面的Subject會循環(huán)調(diào)用每個(gè)觀察者的watch()方法,所以我們需要實(shí)現(xiàn)每個(gè)觀察者的watch()方法。
調(diào)用
// 應(yīng)用實(shí)例 $action=new Action(); $action->register(new Cat()); $action->register(new People()); $action->register(new Dog()); $action->notify();
首先new被觀察者對象,執(zhí)行它的register()方法,把每個(gè)觀察者都放入容器數(shù)組,最后執(zhí)行notify()方法,通知所有觀察者執(zhí)行自己的方法。
PHP原生自帶的觀察者模式
PHP有自帶的觀察者模式
首先我們有一個(gè)用戶登錄類
class user{ public function login() { echo '登錄完畢' }
讓他實(shí)現(xiàn)splsubject接口成為被觀察者。
class user implements splsubject{ protected $observer = null; public function __construct() { $this->observer = new SplObjectStorage(); } public function login() { $this->notify(); echo '登錄完畢'; } public function attach(SplObserver $observer) { $this->observer->attach($observer); } public function detach(SplObserver $observer) { $this->observer->detach($observer); } public function notify() { $this->observer->rewind(); while ($this->observer->valid()) { $observer = $this->observer->current(); $observer->update($this); $this->observer->next(); } } }
觀察者
每個(gè)觀察者實(shí)現(xiàn)SplObserver接口,并實(shí)現(xiàn)update()方法
class cat implements SplObserver { public function update(SplSubject $subject) { echo '小貓叫一下'; } } class dog implements SplObserver { public function update(SplSubject $subject) { echo '小狗吼一聲'; } }
應(yīng)用
// 實(shí)時(shí)觀察 $user = new user(); $user->attach(new cat()); $user->attach(new dog()); $user->login();
以上就是解析PHP觀察者模式(Observer)的詳細(xì)內(nèi)容,更多關(guān)于PHP觀察者模式(Observer)的資料請關(guān)注腳本之家其它相關(guān)文章!
標(biāo)簽:六安 鶴崗 遼陽 鷹潭 克拉瑪依 唐山 柳州 白城
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《解析PHP觀察者模式Observer》,本文關(guān)鍵詞 解析,PHP,觀察者,模式,Observer,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。