初识设计模式——观察者模式(Observer Pattern)
观察者模式(Observer Pattern)又被称为发布-订阅模式(Publish-Subscribe Pattern),是一种行为设计模式,它定义了对象间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。在这个模式里,被观察的对象称为主题(Subject),依赖于主题的对象称为观察者(Observer)
观察者模式的主要构成
1. 抽象主题(Subject)
- 定义:它是一个接口或抽象类,该角色定义了增加、删除、通知观察者对象的方法。
- 作用:为具体主题提供了一个统一的接口,使得具体主题能够被观察者观察,并且可以方便地管理观察者列表。
2. 具体主题(Concrete Subject)
- 定义:抽象主题的具体实现类。它维护一个观察者列表,当自身的状态发生改变时,会调用通知方法来通知所有注册的观察者。
- 作用:负责存储和管理观察者对象,以及在状态改变时触发通知操作。
3. 抽象观察者(Observer)
- 定义:它是一个接口或抽象类,定义了一个更新方法,当主题状态发生改变时,该方法会被调用。
- 作用:为具体观察者提供了一个统一的接口,使得具体观察者能够响应主题的状态变化。
4. 具体观察者(Concrete Observer)
- 定义:抽象观察者的具体实现类。它实现了抽象观察者定义的更新方法,当接收到主题的通知时,会执行相应的更新操作。
- 作用:根据主题的状态变化来更新自身的状态或执行特定的操作。

示例
场景分析
在 Web 开发中,常见的使用观察者模式的案例是事件监听。例如,当用户提交表单时,可能需要触发多个操作,如验证表单数据、记录日志、发送邮件等。这些操作可以作为观察者,而表单提交事件就是主题。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| <?php
interface Observer { public function update($data); }
interface Subject { public function attach(Observer $observer); public function detach(Observer $observer); public function notify(); }
class FormSubmitSubject implements Subject { private $observers = []; private $formData;
public function attach(Observer $observer) { $this->observers[] = $observer; }
public function detach(Observer $observer) { $key = array_search($observer, $this->observers, true); if ($key!== false) { unset($this->observers[$key]); } }
public function notify() { foreach ($this->observers as $observer) { $observer->update($this->formData); } }
public function submitForm($data) { $this->formData = $data; $this->notify(); } }
class FormValidator implements Observer { public function update($data) { echo "表单验证:数据验证通过,数据为 ". json_encode($data). "<br>"; } }
class Logger implements Observer { public function update($data) { echo "日志记录:表单数据已记录,数据为 ". json_encode($data). "<br>"; } }
class MailSender implements Observer { public function update($data) { echo "邮件发送:已发送通知邮件,数据为 ". json_encode($data). "<br>"; } }
$formSubject = new FormSubmitSubject();
$validator = new FormValidator(); $logger = new Logger(); $mailSender = new MailSender();
$formSubject->attach($validator); $formSubject->attach($logger); $formSubject->attach($mailSender);
$formData = ['username' => 'john_doe', 'email' => 'john@example.com']; $formSubject->submitForm($formData);
|
代码含义
在这个示例中,FormSubmitSubject 是主题,当表单提交时,会通知所有的观察者。FormValidator、Logger 和 MailSender 是具体的观察者,它们实现了 Observer 接口,当接收到通知时,会执行相应的操作。
UML类图

观察者模式的优缺点
优点
- 松耦合:主题和观察者之间的耦合度较低,主题不需要知道具体有哪些观察者,只需要维护一个观察者列表,而观察者也不需要知道主题的具体实现细节。
- 可扩展性:可以方便地添加或删除观察者,而不会影响主题和其他观察者的代码。
- 支持广播通信:主题状态变化时,会自动通知所有观察者,实现了一种广播机制。
缺点
- 性能问题:如果观察者数量过多,通知所有观察者可能会导致性能下降。
- 内存泄漏风险:如果观察者没有正确地从主题中移除,可能会导致内存泄漏。
观察者模式适用的业务场景
- 事件处理系统:如 GUI 编程中,当用户点击按钮时,会触发一系列的事件处理程序。
- 状态监控:监控系统资源的使用情况,当资源使用达到一定阈值时,通知相关的监控程序。
- 消息通知系统:如社交网络中,当用户发布新消息时,通知其所有的粉丝。