觀察者模式結(jié)構(gòu)圖
概念
一個"演員"(被觀察者),一群"觀眾"(觀察者),一臺"攝影機"(記錄容器)
【觀察者模式中主要角色】
1.抽象主題(Subject)角色:主題角色將所有對觀察者對象的引用保存在一個集合中,每個主題可以有任意多個觀察者。 抽象主題提供了增加和刪除觀察者對象的接口。
2.抽象觀察者(Observer)角色:為所有的具體觀察者定義一個接口,在觀察的主題發(fā)生改變時更新自己。
3.具體主題(ConcreteSubject)角色:存儲相關(guān)狀態(tài)到具體觀察者對象,當(dāng)具體主題的內(nèi)部狀態(tài)改變時,給所有登記過的觀察者發(fā)出通知。具體主題角色通常用一個具體子類實現(xiàn)。
4.具體觀察者(ConcretedObserver)角色:存儲一個具體主題對象,存儲相關(guān)狀態(tài),實現(xiàn)抽象觀察者角色所要求的更新接口,以使得其自身狀態(tài)和主題的狀態(tài)保持一致。
【使用場景】
假設(shè)項目經(jīng)理讓我們寫了一個登陸接口,咔咔擦擦寫完了
第二天讓我們加入統(tǒng)計登陸次數(shù),然后在后面加代碼第三天讓我們判斷登陸地區(qū),又在后面加代碼第四天讓我們在用戶登陸后推送活動,再再后面加代碼第N天,這個接口已經(jīng)雜亂到?jī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實現(xiàn)了被觀察者接口,他現(xiàn)在就是被觀察者,再定義一個$_observers數(shù)組,他就是記錄觀眾的容器了。
首先實現(xiàn)register方法,用它傳入一個觀察者,然后塞到數(shù)組里,再實現(xiàn)notify()方法,它會遍歷容器數(shù)組,執(zhí)行每個觀察者的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/>";
}
}
這里定義了三個觀察者,全都實現(xiàn)了Observer接口,前面的Subject會循環(huán)調(diào)用每個觀察者的watch()方法,所以我們需要實現(xiàn)每個觀察者的watch()方法。
調(diào)用
// 應(yīng)用實例
$action=new Action();
$action->register(new Cat());
$action->register(new People());
$action->register(new Dog());
$action->notify();
首先new被觀察者對象,執(zhí)行它的register()方法,把每個觀察者都放入容器數(shù)組,最后執(zhí)行notify()方法,通知所有觀察者執(zhí)行自己的方法。
PHP原生自帶的觀察者模式
PHP有自帶的觀察者模式
- splsubject接口 - 被觀察者
- Observer接口 - 觀察者
- SplObjectStorage對象 - 容器
首先我們有一個用戶登錄類
class user{
public function login()
{
echo '登錄完畢'
}
讓他實現(xiàn)splsubject接口成為被觀察者。
- 首先在構(gòu)造函數(shù)里,讓他new SplObjectStorag()對象并賦值到屬性上方便后面調(diào)用
- 實現(xiàn)attach()方法,用來注冊觀察者
- 實現(xiàn)detach()方法,用來刪除觀察者
- 實現(xiàn)notify()方法,用來遍歷容器,調(diào)用每個觀察者的update方法(必須是update)
- rewind方法是容器指針重置到最開始,valid方法檢測容器是否遍歷完成并返回布爾,current方法是獲取當(dāng)前的觀察者,next方法是將指針后移一位
- 修改login()方法,在里面調(diào)用notify()來通知觀察者事件完成了
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();
}
}
}
觀察者
每個觀察者實現(xiàn)SplObserver接口,并實現(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)用
// 實時觀察
$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)文章!
您可能感興趣的文章:- PHP設(shè)計模式之觀察者模式入門與應(yīng)用案例詳解
- PHP 觀察者模式深入理解與應(yīng)用分析
- php模式設(shè)計之觀察者模式應(yīng)用實例分析
- PHP使用觀察者模式處理異常信息的方法詳解
- php設(shè)計模式之觀察者模式定義與用法經(jīng)典示例
- PHP中常用的三種設(shè)計模式詳解【單例模式、工廠模式、觀察者模式】
- PHP觀察者模式實例分析【對比JS觀察者模式】
- PHP設(shè)計模式之觀察者模式定義與用法分析
- PHP觀察者模式定義與用法實例分析