假設項目經理讓咱們寫了一個登錄接口,咔咔擦擦寫完了php
次日讓咱們加入統計登錄次數,而後在後面加代碼laravel
第三天讓咱們判斷登錄地區,又在後面加代碼面試
第四天讓咱們在用戶登錄後推送活動,再再後面加代碼sql
第N天,這個接口已經雜亂到沒人想維護了shell
咱們須要讓項目保持高內聚低耦合,就能夠用到觀察者模式(也不是非要,看需求)數組
觀察者,觀察者,首先要有個被人觀察的角色,這是惟一的,而後會有無數個觀察者去看她,能夠說是一羣人在圍觀一我的,既然有無數個觀衆,那總得有個東西記錄有哪些觀察者,那就應該有一個相似於數組同樣來儲存全部觀察者,總結就是一個被觀察者,無數個觀察者,再有一個容器記錄服務器
★個人php高級學習交流社羣「點擊」管理準備好的社羣專屬資料:BAT等一線大廠進階知識體系(相關學習資料以及筆面試題)以及不限於:分佈式架構、高可擴展、高性能、高併發、服務器性能調優、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql優化、shell腳本、Docker、微服務、Nginx等多個知識點高級進階乾貨架構
// 主題接口 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實現了被觀察者接口,他如今就是被觀察者,再定義一個$_observers數組,他就是記錄觀衆的容器了。分佈式
首先實現register方法,用它傳入一個觀察者,而後塞到數組裏,再實現notify()方法,它會遍歷容器數組,執行每一個觀察者的watch()方法。
// 觀察者 class Cat implements Observer{ public function watch(){ echo "Cat watches TV<hr/>"; } } class Dog implements Observer{ public function watch(){ echo "Dog watches TV<hr/>"; } } class People implements Observer{ public function watch(){ echo "People watches TV<hr/>"; } }
這裏定義了三個觀察者,全都實現了Observer接口,前面的Subject會循環調用每一個觀察者的watch()方法,因此咱們須要實現每一個觀察者的watch()方法。
// 應用實例 $action=new Action(); $action->register(new Cat()); $action->register(new People()); $action->register(new Dog()); $action->notify();
首先new被觀察者對象,執行它的register()方法,把每一個觀察者都放入容器數組,最後執行notify()方法,通知全部觀察者執行本身的方法。
PHP有自帶的觀察者模式
splsubject接口 - 被觀察者
Observer接口 - 觀察者
SplObjectStorage對象 - 容器
首先咱們有一個用戶登陸類
class user{ public function login() { echo '登陸完畢' }
讓他實現splsubject接口成爲被觀察者。
首先在構造函數裏,讓他new SplObjectStorag()對象並賦值到屬性上方便後面調用
實現attach()方法,用來註冊觀察者
實現detach()方法,用來刪除觀察者
實現notify()方法,用來遍歷容器,調用每一個觀察者的update方法(必須是update)
rewind方法是容器指針重置到最開始,valid方法檢測容器是否遍歷完成並返回布爾,current方法是獲取當前的觀察者,next方法是將指針後移一位
修改login()方法,在裏面調用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(); } } }
每一個觀察者實現SplObserver接口,並實現update()方法
class cat implements SplObserver { public function update(SplSubject $subject) { echo '小貓叫一下'; } } class dog implements SplObserver { public function update(SplSubject $subject) { echo '小狗吼一聲'; } }
// 實時觀察 $user = new user(); $user->attach(new cat()); $user->attach(new dog()); $user->login();
PHP 互聯網架構師 50K 成長指南+行業問題解決總綱(持續更新)
面試10家公司,收穫9個offer,2020年PHP 面試問題
★若是喜歡個人文章,想與更多資深開發者一塊兒交流學習的話,獲取更多大廠面試相關技術諮詢和指導,歡迎加入咱們的羣-點擊此處。
本文由博客羣發一文多發等運營工具平臺 OpenWrite 發佈