观察者模式
介绍
观察者模式,属于⾏为型模式的⼀种,它定义了⼀种⼀对多的依赖关系,让多个观察者对象同时监听某⼀个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使所有依赖于它的对象都得到通知并被自动更新。
模型的结构
- Subject:抽象主题,他把所有观察者对象保存在一个集合里,可以有任意数量的观察者对象,抽象主体提供一个接口,可以增加和删除观察者对象。
- ConcreteSubject:具体主题,该⻆⾊将有关状态存⼊具体观察者对象,在具体主题的内部状态发⽣改变时,给所有注册过的观察者发送通知。意思是当观察者对象发生改变时,就会立刻通知所有观察者。
- Observer:抽象观察者,是观察者的抽象类,它定义了一个更新接口,也就是说,在得到主题更改通知的时候更改自己。
- ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
//观察者对象主题
interface Subject{
public function regsiter(Observer $observer);
public function notify($info);
}
//张三 李四和王五
class zhangsan implements Subject{
public $observers = array();
public function regsiter(Observer $observer)
{
$this->observers[] = $observer;
}
public function notify($info)
{
foreach ($this->observers as $observer){
$observer->watch($info);
}
}
}
//观察者主题
interface Observer{
public function watch($info);
}
class lisi implements Observer{
public function watch($info)
{
echo "我是李四,我现在知道张三$info\n";
}
}
class wangwu implements Observer{
public function watch($info)
{
echo "我是王五,我现在知道张三$info\n";
}
}
$zhangsan = new zhangsan();
$zhangsan->regsiter(new lisi());
$zhangsan->regsiter(new wangwu());
$zhangsan->notify('有钱');
优缺点
- 优点
观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。
- 缺点
如果⼀个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
如果在观察者和观察⽬标之间有循环依赖的话,观察⽬标会触发它们之间进⾏循环调⽤,可能导致系统崩溃。
观察者模式没有相应的机制让观察者知道所观察的⽬标对象是怎么发⽣变化的,⽽仅仅只是知道观察⽬标发⽣了变化。
应用场景
- 当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
- 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象需要被改变。
- 当一个对象必须通知其他对象,而它又不能假定其他对象是谁。
- 举个例子,就好比如追星,有明星就是观察者对象,粉丝就是观察者,当明星发布动态的时候,他并不需要知道谁可以看到,也不需要知道多少人可以看到。