觀察者,貌似在不少科幻做品中都會有這個角色的出現。好比我很喜歡的一部美劇《危機邊緣》,在這個劇集中,觀察者不停的穿越時空記錄着各類各樣的人或事。可是,設計模式中的觀察者可不僅是站在邊上看哦,這裏的觀察者是針對主體發生的狀態改變來作出對應的動做。php
GoF定義:定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都獲得通知並被自動更新git
GoF類圖github
代碼實現數據庫
interface Observer {
public function update(Subject $subject): void;
}
複製代碼
觀察者的抽象接口,沒啥可說的吧,就是讓你實現一個具體的Update就能夠了編程
class ConcreteObserver implements Observer {
private $observerState = '';
function update(Subject $subject): void {
$this->observerState = $subject->getState();
echo '執行觀察者操做!當前狀態:' . $this->observerState;
}
}
複製代碼
具體的觀察者,實現update()方法,這裏咱們拿到了Subject類,從而能夠得到其中的狀態設計模式
class Subject {
private $observers = [];
private $stateNow = '';
public function attach(Observer $observer): void {
array_push($this->observers, $observer);
}
public function detach(Observer $observer): void {
$position = 0;
foreach ($this->observers as $ob) {
if ($ob == $observer) {
array_splice($this->observers, ($position), 1);
}
++$position;
}
}
public function notify(): void {
foreach ($this->observers as $ob) {
$ob->update($this);
}
}
}
複製代碼
Subject父類,維護一個觀察者數組,而後有添加、刪除以及循環遍歷這個數組的方法,目的是可以方便的管理全部的觀察者數組
class ConcreteSubject extends Subject{
public function setState($state) {
$this->stateNow = $state;
$this->notify();
}
public function getState() {
return $this->stateNow;
}
}
複製代碼
Subject的實現類,只是更新了狀態,在這個狀態發生改變的時候,調用觀察者遍歷的方法進行全部觀察的update()操做編程語言
接着拿咱們的手機工廠說事兒,此次好嘛,被一幫山寨機盯上了(觀察者),我出什麼功能(狀態更新),他們就對應的出同樣的功能(更新),並且還在個人基礎上作了更多的東西,美其名曰:微創新!你說氣人不氣人。好吧,我也派出了一幫市場調查人員(觀察者),去幫我觀察別人家的手機都出了什麼功能(狀態更新),而後咱們也照搬過來搞點微創新,你們共同進步嘛!!this
完整代碼:github.com/zhangyue050…spa
此次咱們從訂單提及,不過仍是有短信發送的事兒。當通常的電商平臺有人下單以後,須要作的事情很是多,好比修改庫存、發送短信或者推送告訴商家有人下單了,告訴買家下單成功了,支付成功了。總之就是一件事情的發生會致使各類事件的產生。其實,這裏就引出了另外一個很是出名的模式訂閱發佈模式。這個模式能夠說是觀察者的升級模式,這個系列的文章不會細講,可是你們能夠去看看Laravel中的發佈訂閱及事件監聽方面的內容。
訂單售出類圖
interface Observer {
public function update($obj);
}
class Message implements Observer {
//....
function update($obj) {
echo '發送新訂單短信(' . $obj->mobile . ')通知給商家!';
}
//....
}
class Goods implements Observer {
//....
public function update($obj) {
echo '修改商品' . $obj->goodsId . '的庫存!';
}
//....
}
class Order {
private $observers = [];
public function attach($ob) {
$this->observers[] = $ob;
}
public function detach($ob) {
$position = 0;
foreach ($this->observers as $ob) {
if ($ob == $observer) {
array_splice($this->observers, ($position), 1);
}
++$position;
}
}
public function notify($obj) {
foreach ($this->observers as $ob) {
$ob->update($obj);
}
}
public function sale() {
// 商品賣掉了
// ....
$obj = new stdClass();
$obj->mobile = '13888888888';
$obj->goodsId = 'Order11111111';
$this->notify($obj);
}
}
$message = new Message();
$goods = new Goods();
$order = new Order();
$order->attach($message);
$order->attach($goods);
// 訂單賣出了!!
$order->sale();
複製代碼
說明
SPL擴展實現觀察者模式-完整源碼:github.com/zhangyue050…
循環是編程語言的一個亮點,由於這個能力讓編程語言作出來的軟件能夠替代人們去作不少重複的勞動。一說到這裏,有的人立刻就會想到,莫非咱們下次講的就是迭代器模式?拭目以待吧!