php面向对象:观察者模式示例

观察者模式也是php面向对象中的一个不常用的模式了,下面我们一起来看看php面向对象:观察者模式示例,希望对给各位带来帮助.

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新【GOF95】,又称为发布-订阅(Publish-Subscribe)模式、模型-视图(Model-View)模式、源-监听(Source-Listener)模式、或从属者(Dependents)模式.

主要角色:抽象主题(Subject)角色:主题角色将所有对观察者对象的引用保存在一个集合中,每个主题可以有任意多个观察者,抽象主题提供了增加和删除观察者对象的接口.

抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在观察的主题发生改变时更新自己.

具体主题(ConcreteSubject)角色:存储相关状态到具体观察者对象,当具体主题的内部状态改变时,给所有登记过的观察者发出通知,具体主题角色通常用一个具体子类实现.

具体观察者(ConcretedObserver)角色:存储一个具体主题对象,存储相关状态,实现抽象观察者角色所要求的更新接口,以使得其自身状态和主题的状态保持一致.

优点和缺点

优点:观察者和主题之间的耦合度较小,支持广播通信.

缺点:由于观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知,这可能会引起意外的更新.

适用场景

当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,当对一个对象的改变需要同时改变其它对象,而不知道具体有多少个对象待改变.

当一个对象必须通知其它对象,而它又不能假定其它对象是谁,换句话说,你不希望这些对象是紧密耦合的.实现代码:

  1. <?php
  2. /**
  3. * 观察者模式
  4. * @package design pattern
  5. */
  6. /**
  7. * 抽象主题角色
  8. */
  9. interface Subject {
  10. /**
  11. * 增加一个新的观察者对象
  12. * @param Observer $observer
  13. */
  14. public function attach(Observer $observer);
  15. /**
  16. * 删除一个已注册过的观察者对象
  17. * @param Observer $observer
  18. */
  19. public function detach(Observer $observer);
  20. /**
  21. * 通知所有注册过的观察者对象
  22. */
  23. public function notifyObservers();
  24. }
  25. /**
  26. * 具体主题角色
  27. */
  28. class ConcreteSubject implements Subject {
  29. private $_observers;
  30. public function __construct() {
  31. $this->_observers = array();
  32. }
  33. /**
  34. * 增加一个新的观察者对象
  35. * @param Observer $observer
  36. */
  37. public function attach(Observer $observer) {
  38. return array_push($this->_observers, $observer);
  39. }
  40. /**
  41. * 删除一个已注册过的观察者对象
  42. * @param Observer $observer
  43. */
  44. public function detach(Observer $observer) {
  45. $index = array_search($observer, $this->_observers);
  46. if ($index === FALSE || ! array_key_exists($index, $this->_observers)) {
  47. return FALSE;
  48. }
  49. unset($this->_observers[$index]);
  50. return TRUE;
  51. }
  52. /**
  53. * 通知所有注册过的观察者对象
  54. */
  55. public function notifyObservers() {
  56. if (!is_array($this->_observers)) {
  57. return FALSE;
  58. }
  59. foreach ($this->_observers as $observer) {
  60. $observer->update();
  61. }
  62. return TRUE;
  63. }
  64. }
  65. /**
  66. * 抽象观察者角色
  67. */
  68. interface Observer {
  69. /**
  70. * 更新方法
  71. */
  72. public function update();
  73. }
  74. class ConcreteObserver implements Observer {
  75. /**
  76. * 观察者的名称
  77. * @var <type>
  78. */
  79. private $_name;
  80. public function __construct($name) {
  81. $this->_name = $name;
  82. }
  83. /**
  84. * 更新方法
  85. */
  86. public function update() {
  87. echo 'Observer', $this->_name, ' has notified.<br />';
  88. } //开源软件:phpfensi.com
  89. }
  90. $subject = new ConcreteSubject();
  91. /* 添加第一个观察者 */
  92. $observer1 = new ConcreteObserver('Martin');
  93. $subject->attach($observer1);
  94. echo '<br /> The First notify:<br />';
  95. $subject->notifyObservers();
  96. /* 添加第二个观察者 */
  97. $observer2 = new ConcreteObserver('phppan');
  98. $subject->attach($observer2);
  99. echo '<br /> The Second notify:<br />';
  100. $subject->notifyObservers();
  101. /* 删除第一个观察者 */
  102. $subject->detach($observer1);
  103. echo '<br /> The Third notify:<br />';
  104. $subject->notifyObservers();
  105. ?>