观察者,貌似在很多科幻作品中都会有这个角色的出现。比如我很喜欢的一部美剧《危机边缘》,在这个剧集中,观察者不停的穿越时空记录着各种各样的人或事。但是,设计模式中的观察者可不只是站在边上看哦,这里的观察者是针对主体发生的状态改变来做出对应的动作。
GoF定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
GoF类图
代码实现
interface Observer{ public function update(Subject $subject): void;}
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; }}
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); } }}
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
$ob->update($this);
Subject父类,维护一个观察者数组,然后有添加、删除以及循环遍历这个数组的方法,目的是能够方便的管理所有的观察者
class ConcreteSubject extends Subject{ public function setState($state) { $this->stateNow = $state; $this->notify(); } public function getState() { return $this->stateNow; }}
class ConcreteSubject extends Subject{
public function setState($state)
$this->stateNow = $state;
$this->notify();
public function getState()
return $this->stateNow;
Subject的实现类,只是更新了状态,在这个状态发生改变的时候,调用观察者遍历的方法进行所有观察的update()操作
接着拿我们的手机工厂说事儿,这次好嘛,被一帮山寨机盯上了(观察者),我出什么功能(状态更新),他们就对应的出一样的功能(更新),而且还在我的基础上做了更多的东西,美其名曰:微创新!你说气人不气人。好吧,我也派出了一帮市场调查人员(观察者),去帮我观察别人家的手机都出了什么功能(状态更新),然后我们也照搬过来搞点微创新,大家共同进步嘛!!
完整代码:https://github.com/zhangyue0503/designpatterns-php/blob/master/06.observer/source/observer.php
这次我们从订单说起,不过还是有短信发送的事儿。当一般的电商平台有人下单之后,需要做的事情非常多,比如修改库存、发送短信或者推送告诉商家有人下单了,告诉买家下单成功了,支付成功了。总之就是一件事情的发生会导致各种事件的产生。其实,这里就引出了另一个非常出名的模式订阅发布模式。这个模式可以说是观察者的升级模式,这个系列的文章不会细讲,但是大家可以去看看Laravel中的发布订阅及事件监听方面的内容。
订单售出类图
完整源码:https://github.com/zhangyue0503/designpatterns-php/blob/master/06.observer/source/order-observer.php
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();
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
public function attach($ob)
$this->observers[] = $ob;
public function detach($ob)
public function notify($obj)
$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();
说明
完整源码:https://github.com/zhangyue0503/designpatterns-php/blob/master/06.observer/source/spl_observer.php
循环是编程语言的一个亮点,因为这个能力让编程语言做出来的软件可以替代人们去做很多重复的劳动。一说到这里,有的人马上就会想到,莫非我们下次讲的就是迭代器模式?拭目以待吧!
===============
关注公众号:【硬核项目经理】获取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料
知乎、公众号、抖音、头条搜索【硬核项目经理】
B站ID:482780532
原文链接:http://www.cnblogs.com/zyblog-coder/p/14142112.html
本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728