初学设计模式之观察者模式

                                                                                                         @[TOC](观察者模式)

观察者模式定义

观察者模式又称发布-订阅模式,定义了一种一对多的依赖关系,让多个观察者同时监听某一个主题对象,当主题对象发生变化时会通知所有观察者对象,使他们能够更新自己

从故事开始

老高:今天摸鱼看股票又被老板抓住了,半天工资没了
老摸:你可以贿赂一下前台小美,等老板回公司的时候就给你发消息,你就可以及时切换到工作面板了
老高:好主意,我这就去买奶茶

用代码描述故事

前台秘书类 (监听:用来监听老板有没有回来)

class Secretary
{public $observers = [];public $action = '';// 添加public function attach(StockObserver $observer){$this->observers = array_merge($this->observers, $observer);return $this;}// 通知public function notify(){foreach ($this->observers as $observer) {$observer->update();}}public function setAction($name){return $this->action = $name;}
}

看股票的同事 (观察者:老板来了改变自己的状态)

class StockObserver
{public $name = '';public $sub;public function __construct($name,Secretary9 $sub){$sub->setAction($name);}public function update(){$action = $this->sub->action;return $this->name + "关闭股票继续工作!"+$action;}
}

控制器中使用观察者模式 (小美如何向同事发消息)

class Controller
{public function run(){$tongzhi = new Secretary();$laogao = new StockObserver("老高", $tongzhi);$laomo = new StockObserver("老摸", $tongzhi);$tongzhi->attach($laogao);$tongzhi->attach($laomo);$tongzhi->action = "老板来了";return $tongzhi->notify();}
}

解耦

故事讲完了,但是代码也实现了,但是问题也出现了,
问题:

  1. 如果有的同事在看直播而不是股票呢,那小美岂不是通知错
  2. 如果小美休假小帅值班,那通知者就是小帅而不是小美
    对于这种情况最简单粗暴的方式就是加一个前台小帅秘书类 和一个看直播的同事类
    但是这样代码重复就很多了,所以这段代码需要解耦
抽离前台秘书类

前台秘书类接口

interface Subject
{public function attach(Observer $observer);public function notify();public function setAction($name);
}

前台秘书小美类

class XiaoMei implements Subject
{public $observers = [];public $action = '';// 添加public function attach(Observer $observer){$this->observers = array_merge($this->observers, $observer);return $this;}// 通知public function notify(){foreach ($this->observers as $observer) {$observer->update();}}public function setAction($name){return $this->action = $name;}
}

前台秘书小帅类

与小美的代码类似此处略
抽离观察者

摸鱼同事接口类

abstract class Observer
{public $name = '';public $sub;public function __construct($name,Subject $sub){$sub->setAction($name);}abstract public function update();
}

看股票同事接口类

class StockObserver extends Observer
{public function update(){$action = $this->sub->action;return $this->name + "关闭股票继续工作!"+$action;}
}

看直播同事接口类

class LiveObserver extends Observer
{public function update(){$action = $this->sub->action;return $this->name + "关闭直播继续工作!"+$action;}
}

控制器中使用观察者模式

class Controller
{public function run(){$tongzhi = new XiaoMei();$laogao = new StockObserver("老高", $tongzhi);$laomo = new NBAObserver("老摸", $tongzhi);$tongzhi->attach($laogao);$tongzhi->attach($laomo);$tongzhi->action = "老板来了~~";return $tongzhi->notify();}
}

总结

观察者模式是将一个系统分割成一系列相互写作的类,有一个很不好的副作用就是需要维护相关对象的一致性。一个主题subject(秘书)可以有任意个观察者observer(同事),一但主题subject(秘书)发生改变,所有的观察者observer(同事)都会得到通知

什么时候使用呢?

当一个对象的改变需要同时改变其他对象的时候,而且它不知道具体有多少对象待改变的情况下,这个时候应该考虑使用观察者模式

有什么优势呢

观察者模式所做的工作其实就是在解耦合,让耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响另一边的变化

观察者模式的不足
  1. 抽象通知者Subject(前台秘书类接口)还是依赖抽象观察者Observer(摸鱼同事接口类),万一没有抽象观察者这样的接口,我这个功能就完不成了,
  2. 另外每一个功能并不一定是更新(update)的时候才会使用,或者隐藏(hidden)的时候也会使用,更新和隐藏者两个是不同名的方法


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部