初学设计模式之观察者模式
@[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();}
}
解耦
故事讲完了,但是代码也实现了,但是问题也出现了,
问题:
- 如果有的同事在看直播而不是股票呢,那小美岂不是通知错
- 如果小美休假小帅值班,那通知者就是小帅而不是小美
对于这种情况最简单粗暴的方式就是加一个前台小帅秘书类 和一个看直播的同事类
但是这样代码重复就很多了,所以这段代码需要解耦
抽离前台秘书类
前台秘书类接口
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(同事)都会得到通知
什么时候使用呢?
当一个对象的改变需要同时改变其他对象的时候,而且它不知道具体有多少对象待改变的情况下,这个时候应该考虑使用观察者模式
有什么优势呢
观察者模式所做的工作其实就是在解耦合,让耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响另一边的变化
观察者模式的不足
- 抽象通知者Subject(前台秘书类接口)还是依赖抽象观察者Observer(摸鱼同事接口类),万一没有抽象观察者这样的接口,我这个功能就完不成了,
- 另外每一个功能并不一定是更新(update)的时候才会使用,或者隐藏(hidden)的时候也会使用,更新和隐藏者两个是不同名的方法
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
