观察者模式是行为型模式的一种,定义了对象间一对多的关系。当对象的状态发生变化时候,依赖于它的对象会得到通知。
方便扩展,降低耦合,统一触发规则。当需要新增或者删除一个观察者的时候,只需要增加观察者就行。
//假设用户成功购买商品后需要发送邮件和短信通知 class Order { private $observers = []; //添加观察者 public function attach($type, $observer) { $this->observers[$type] = $observer; } //对每个观察者进行通知 public function notify() { if ($this->observers == []) { return null; } foreach ($this->observers as $every_observer) { (new $every_observer)->update($this); } } //购买商品,触发通知 public function buyGoods() { //todo 订单操作 echo '商品购买完成' . PHP_EOL; $this->notify(); } } class Mail { public function update($observer) { echo '发送电子邮件' . PHP_EOL; } } class Sms { public function update($observer) { echo '发送短信' . PHP_EOL; } } $order = new Order(); //添加观察者 $order->attach('mail', Mail::class); $order->attach('sms', Sms::class); $order->buyGoods();
SPL(Standard PHP Library)标准PHP类库,用于解决典型问题的一组接口与类的集合。
class OrderListener implements \SplSubject { //观察者列表 public $observers; public function __construct() { //SplObjectStorage类提供从对象到数据的映射,或者通过忽略数据,提供对象集的映射。在许多需要唯一标识对象的情况下,这种双重用途非常有用。 $this->observers = new \SplObjectStorage(); } //添加要通知的对象 public function attach(\SplObserver $observer) { $this->observers->attach($observer); } //移除要通知的对象 public function detach(\SplObserver $observer) { $this->observers->detach($observer); } //通知 public function notify() { //将迭代器(此处可以理解为指针)倒回到第一个存储元素。 $this->observers->rewind(); //判断指针是否有效 while($this->observers->valid()) { //获取当前的观察者 $curr_obj = $this->observers->current(); //对当前观察者进行通知 $curr_obj->update($this); //向下移动指针 $this->observers->next(); } } //触发通知 public function buyGoods() { echo '购买成功' . PHP_EOL; $this->notify(); } } //SplObserver接口与SplSubject接口一起使用,以实现观察者设计模式。 class Mail implements \SplObserver { //对被观察的对象做相应的处理 public function update(\SplSubject $subject) { echo '发送邮件' . PHP_EOL; } } class Sms implements \SplObserver { //对被观察的对象做相应的处理 public function update(\SplSubject $subject) { echo '发送短信' . PHP_EOL; } } $listener = new OrderListener(); //添加观察者 $listener->attach(new Mail()); $listener->attach(new Sms()); $listener->buyGoods();
通知代码(基于SPL实现的notify方法优化)
//以上代码的notify方法使用原生手动调整指针的方式去实现。也可以使用foreach去遍历实现 public function notify() { foreach ($this->observers as $observer) { $observer->update($this); } }
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。