观察者模式又叫发布订阅模式, 其本质是在被观察者对象中注册一系列的观察者, 当被观察者的状态发生改变的时候, 通过循环调用一系列观察者对象的方法,进而让观察者对被观察者的状态改变做出相应的响应。PHP也内建了观察者模式的接口点击这里查看php定义的观察者接口 被观察者接口

优点

  1. 降低了被观察者与观察者之间的耦合性, 双方都是依赖抽象而不是具体的实现(面向接口编程)。

缺点

  1. 由于是一对多的关系而且php是同步执行, 所以其中含有执行效率低的观察者,将影响整体的执行效率,也会加大php的内存占用(所有的监听者都会被实例化并存储), 所以要根据实际需要来使用。(使用异步是一种解决方案)

应用

  1. <?php
  2. // 被观察者, 使用标准库提供的对象存储,存储所有的观察者
  3. class FileUpload implements SplSubject
  4. {
  5. private $storage;
  6. private $filename;
  7. public function __construct($filename)
  8. {
  9. echo '上传了一张新图片' . $filename . PHP_EOL;
  10. $this->storage = new SplObjectStorage();
  11. $this->filename = $filename;
  12. }
  13. public function attach(SplObserver $observer)
  14. {
  15. $this->storage->attach($observer);
  16. }
  17. public function detach(SplObserver $observer)
  18. {
  19. $this->storage->detach($observer);
  20. }
  21. public function notify()
  22. {
  23. foreach ($this->storage as $obj){
  24. $obj->update($this);
  25. }
  26. }
  27. public function getFilename(){
  28. return $this->filename;
  29. }
  30. }
  1. <?php
  2. // 通知朋友, 新分享了一个文件
  3. class Friends implements SplObserver
  4. {
  5. public function update(SplSubject $subject)
  6. {
  7. echo '收到了一个分享' . $subject->getFilename() . PHP_EOL;
  8. }
  9. }
  1. <?php
  2. // 接收到通知的时候生成缩略图
  3. class Thumbnail implements SplObserver{
  4. public function update(SplSubject $subject)
  5. {
  6. echo $subject->getFilename() . '生成缩略图成功' . PHP_EOL;
  7. }
  8. }
  1. <?php
  2. // 场景类
  3. require_once "FileUpload.php";
  4. require_once "Thumbnail.php";
  5. require_once "Friends.php";
  6. $fileL = new FileUpload('图片1.png');
  7. $thumbnail = new Thumbnail();
  8. $fileL->attach($thumbnail); // 增加一个监听者
  9. $fileL->attach(new Friends());
  10. $fileL->detach($thumbnail); // 不想生成缩略图也可以取消监听
  11. $fileL->notify();

结果:
上传了一张新图片图片1.png
图片1.png生成缩略图成功
收到了一个分享图片1.png

应用场景

  1. 关联行为场景, 例如 a的状态改变会影响到 b,c, 或者其他对象
  2. 事件多级触发, 类似一次框架的运行流程, 接到请求—>初始化框架—>处理请求—>返回相应(这种情况下, 观察者同时也是被观察者)
  3. 跨系统的消息交换,如消息队列的处理

实践

  1. 在文件上传时, 可能发生下列动作
    1. 检查文件类型
    2. 如果是图片要生成缩略图
    3. 减少用户的可用空间
    4. 如果是分享的文件, 还要通知其他人,有人新分享了一个文件

实际中这种场景应该是很多的。