23种设计模式-观察者模式
概述
观察者模式又被称为 发布-订阅
(Publish/Subscribe)模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。
结构
观察者模式有以下角色:
- 抽象主题(Subject):抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
- 具体主题(Concrete Subject):该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
- 抽象观察者(Observer):是观察者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
- 具体观察者(Concrete Observer):实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
实现
/**
* 抽象观察者
*/
interface Observer
{
public function handle();
}
/**
* 抽象主题
*/
interface Subject
{
public function addObserver(Observer $observer);
public function delObserver(Observer $observer);
public function notifyObserver();
}
class Event implements Subject
{
protected $observers;
public function addObserver(Observer $observer)
{
$this->observers[] = $observer;
}
public function delObserver(Observer $observer)
{
foreach ($this->observers as $k => $v) {
if ($v === $observer) {
unset($this->observers[$k]);
}
}
}
public function notifyObserver()
{
foreach ($this->observers as $observer) {
$observer->handle();
}
}
}
/**
* 具体观察者
*/
class Listener implements Observer
{
public function handle()
{
echo '监听事件了';
}
}
/**
* 具体主题
*/
class Job extends Event
{
public function dispatch()
{
$this->notifyObserver();
}
}
// 测试
$subject = new Job();
$subject->addObserver(new Listener());
$subject->dispatch();
优缺点
- 优点
- 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
- 被观察者发送通知,所有注册的观察者都会收到信息,实现了广播机制
- 缺点
- 如果观察者非常多的话,那么所有观察者收到被观察者发送的通知会耗时长
- 如果被观察者有循环依赖的话,那么被观察者发送通知会使观察者循环调用,会导致系统崩溃
使用场景
- 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
- 当一个抽象模型有两个方面,其中一个方面依赖另一个方面时。