定义

在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。一般情况下,被依赖的对象叫作被观察者(Observable),依赖的对象叫作观察者(Observer)。

实现方式

有同步阻塞的实现方式,也有异步非阻塞的实现方式;有进程内的实现方式,也有跨进程的实现方式。

  1. <?php
  2. abstract class Subject
  3. {
  4. private $observers = [];
  5. public function attach(Observer $observer)
  6. {
  7. array_push($this->observers, $observer);
  8. }
  9. public function detatch($observer)
  10. {
  11. foreach ($this->observers as $key => $value) {
  12. if ($observer === $value) {
  13. unset($this->observers[$key]);
  14. }
  15. }
  16. }
  17. public function notify()
  18. {
  19. foreach ($this->observers as $observer) {
  20. $observer->update();
  21. }
  22. }
  23. }
  24. abstract class Observer
  25. {
  26. abstract function update();
  27. }
  28. class ConcreteSubject extends Subject
  29. {
  30. private $subjectState;
  31. public function setState($state)
  32. {
  33. $this->subjectState = $state;
  34. }
  35. public function getState()
  36. {
  37. return $this->subjectState;
  38. }
  39. }
  40. class ConcreteObserver extends Observer
  41. {
  42. private $name;
  43. private $subject;
  44. function __construct(ConcreteSubject $subject, $name)
  45. {
  46. $this->subject = $subject;
  47. $this->name = $name;
  48. }
  49. public function update()
  50. {
  51. echo "观察者 ".$this->name."的新状态是:".$this->subject->getState()."\n";
  52. }
  53. }
  54. $s = new ConcreteSubject();
  55. $s->attach(new ConcreteObserver($s, "x"));
  56. $s->attach(new ConcreteObserver($s, "y"));
  57. $z = new ConcreteObserver($s, "z");
  58. $s->attach($z);
  59. $s->detatch($z);
  60. $s->setState('ABC');
  61. $s->notify();


应用场景

邮件订阅、RSS Feeds,状态机流转。

总结

将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。
观察者模式所做的工作其实就是在接触耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。