一、使用场景
观察者模式,也叫做发布者订阅者模式,是常用的一个设计模式,实际应用开发中经常可以看到观察者模式的影子,如JavaScript中的事件监听就是运用到了观察者模式的思想。观察者模式适用于 当一个对象的改变需要同时改变其他对象,且对象的改变不知道有多少其他对象待改变的时候,就可以使用观察者模式了
二、基本角色
- 通知者(发布者):做出一个状态的改变,并将状态的改变传播到其他对象上
- 观察者(订阅者):受通知者状态改变而执行相应动作的对象
三、实现
这里,我使用PHP实现观察者模式,为了解除耦合,用到了PHP的interface
和类型约束
,通知者和观察者都依赖于抽象,使用接口实现,如:
interface Subject {
public function getStatus();
public function setStatus(Observer observer);
public function attach(Observer observer); // 添加一个新的观察者(订阅)
public function detach(Observer observer); // 删除一个观察者(解除订阅)
public function notify(); // 通知观察者
}
interface Observer {
public function update(); // 当接收到状态改变的时候,要执行的动作
}
这里,我们假设一个场景:某公司各部门的工作听命于公司老板,这就是一种一个对象的状态影响到其他对象的例子,老板的状态(如一个命令),各部门都需要响应。在这种场景下,老板是通知者(发布状态),其他部门的是观察者(响应状态的改变),那么可以实现如下:
class Boss implements Subject {
private $status;
// 观察者列表
private $observerList = array();
public function setStatus($status) {
$this->status = $status;
}
public function getStatus() {
return $this->status;
}
public function attach(Observer $observer) {
if(!in_array($observer, $this->observerList)) {
array_push($this->observerList, $observer);
}
}
public function detach(Observer $observer) {
foreach($this->observerList as $key => $eachObserver) {
if($observer == $eachObserver) {
unset($this->observerList[$key]);
break;
}
}
}
public function notify() {
foreach($this->observerList as $eachObserver) {
$eachObserver->update();
}
}
}
其他部门,如秘书部和董事会:
class Secretary implements Observer {
private $subject;
function __construct(Subject $subject) {
$this->subject = $subject;
}
function update() {
echo $this->subject->getStatus().",马上准备材料!";
echo PHP_EOL;
}
}
class Board implements Observer {
private $subject;
function __construct(Subject $subject) {
$this->subject = $subject;
}
function update() {
echo $this->subject->getStatus().",记得准时到场!";
echo PHP_EOL;
}
}
然后,老板通知今天开重要会议,就可以如下实现:
$boss = new Boss;
$boss->attach(new Secretary($boss));
$boss->attach(new Board($boss));
// 做出状态改变
$boss->setStatus("下午有个重要会议要开");
$boss->notify();
/*
运行结果:
下午有个重要会议要开,马上准备材料!
下午有个重要会议要开,记得准时到场!
*/