> **設計模式-觀察者模式**
## 說明 ##
**觀察者模式(Observer),當一個對象的狀態發生改變時,依賴他的對象會全部收到通知,并自動更新。**
----------
##模式說明##
場景:一個事件發生后,要執行一連串更新操作.傳統的編程方式,就是在事件的代碼之后直接加入處理邏輯,當更新的邏輯增多之后,代碼會變得難以維護.這種方式是耦合的,侵入式的,增加新的邏輯需要改變事件主題的代碼
觀察者模式實現了低耦合,非侵入式的通知與更新機制
在PHP5.1之后,PHP提供了SPL(標準PHP庫 - Standard PHP Library)這個庫,這個庫包括一組解決標準問題的接口和類其中就有觀察者接口。
觀察者模式的核心在于Subject和Observer 接口。Subject包含一個給定的狀態,觀察者"訂閱"這個主題,將主題的當前狀態通知觀察者。可以認為它是一個博客,有很多訂閱者,會定期地為訂閱或定期閱讀博客的各類用戶更新一組信息。每次博客發生改變時(其狀態改變),所有訂閱者"都會得到通知"。
![請輸入圖片描述][1]
SplSubject {
/* 方法 */
abstract public attach ( SplObserver $observer ) : void //附加SplObserver觀察者
abstract public detach ( SplObserver $observer ) : void //分離SplObserver觀察者
abstract public notify ( void ) : void //通知SplObserver觀察者
}
SplObserver {
/* 方法 */
abstract public update ( SplSubject $subject ) : void //接收被觀察者更新
}
##示例代碼##
<h5>場景說明</h5>
新用戶注冊之后,對新用戶進行 初始話密碼 和 發送短信接口操作
<h5>被觀察者User類</h5>
//被觀察者,用戶注冊之后 1.初始話密碼 2.發送短信接口
//被觀察者類必須實現SplSubject接口 且實現接口的 attach() detach() notify()方法
class User implements SplSubject {
public $userName;
public $phone;
public $observers; //用來存儲觀察者對象
public function __construct($userName,$phone)
{
$this->userName=$userName;
$this->phone=$phone;
$this->observers = new SplObjectStorage();//SplObjectStorage是SPL標準庫中的數據結構對象容器,用來存儲觀察者對象
}
/**
* @param SplObserver $observer
* 添加觀察者
*/
public function attach(SplObserver $observer)
{
// TODO: Implement attach() method.
$this->observers->attach($observer);
}
/**
* @param SplObserver $observer
* 移除觀察者
*/
public function detach(SplObserver $observer)
{
// TODO: Implement detach() method.
$this->observers->detach($observer);
}
/**
* 執行觀察者操作
*/
public function notify()
{
foreach ($this->observers as $observer) {
$observer->update($this);
}
// TODO: Implement notify() method.
}
//新用戶注冊流程 ,注冊成功執行notify方法
public function register(){
//if(success)
$this->notify();
}
}
<h5>觀察者類</h5>
觀察者UserInit類和SendMessage類
//觀察者 用戶初始化類用來實現用戶注冊后的初始密碼等操作
//觀察者類必須實現SplObserver接口,并實現update() 方法
class UserInit implements SplObserver {
/**
* @param SplSubject $subject
*/
public function update(SplSubject $subject)
{
echo "用戶".$subject->userName."的初始密碼為:".mt_rand(100000, 999999).PHP_EOL;
// TODO: Implement update() method.
}
}
//觀察者 發送短信類用來實現用戶注冊后的將用用戶的信息發送給用戶
//觀察者類必須實現SplObserver接口,并實現update() 方法
class SendMessage implements SplObserver {
/**
* @param SplSubject $subject
*/
public function update(SplSubject $subject)
{
echo "已經向用戶".$subject->userName."手機號".$subject->phone."發送短信".PHP_EOL;
// TODO: Implement update() method.
}
}
<h5>測試</h5>
header('Content-Type: text/plain');
$user=new User("zhangsan","17600128056");
$user->attach(new UserInit());
$user->attach(new SendMessage());
//用戶
$user->register();
<h5>結果</h5>
瀏覽器輸出結果:
用戶zhangsan的初始密碼為:620834
已經向用戶zhangsan手機號17600128056發送短信
## 結尾 ##
<p style="background-image: -webkit-linear-gradient(left, #3498db, #f47920 10%, #d71345 20%, #f7acbc 30%,#ffd400 40%, #3498db 50%, #f47920 60%, #d71345 70%, #f7acbc 80%, #ffd400 90%, #3498db);color: transparent;-webkit-text-fill-color: transparent;-webkit-background-clip: text;text-align:center;">
心如花木,向陽而生。
</p>
[1]: https://blog.zxliu.cn/usr/uploads/2020/11/2353528746.png
[2]: https://blog.zxliu.cn/usr/uploads/2020/11/1966401635.png