1. <?php
  2. /**
  3. * 设计模式之观察者模式
  4. * 使用场景 订阅信息,消息推送
  5. * 小黄牛
  6. */
  7. header("Content-type: text/html; charset=utf-8");
  8. /**
  9. *
  10. * 抽象出通知者类
  11. */
  12. abstract class Subject{
  13. private $observers = array(); // 用户保存观察成员
  14. # 添加观察成员
  15. public function Attach($observer){
  16. array_push($this->observers, $observer);
  17. }
  18. # 删除观察成员
  19. public function Detach($observer){
  20. foreach($this->observers as $k=>$v) {
  21. if($v==$observer) {
  22. unset($this->observers[$k]);
  23. }
  24. }
  25. }
  26. # 向观察成员群发消息
  27. function Notify(){
  28. foreach($this->observers as $v) {
  29. $v->Update();
  30. }
  31. }
  32. }
  33. //具体通知者(Boss和Secretary)
  34. class ConcreteSubject extends Subject{
  35. public $subject_state; // 推送的内容
  36. }
  37. //抽象观察者
  38. abstract class Observer{
  39. public abstract function Update();
  40. }
  41. //具体观察者
  42. class ConcreteObserver extends Observer{
  43. private $name; // 观察者名称
  44. private $observerState; // 保存通知者推送过来的内容
  45. public $subject; // 通知者实例,作用是保证大家都在同一频道内
  46. # 初始化成员属性
  47. public function __construct($_sub,$_name){
  48. $this->subject = $_sub;
  49. $this->name = $_name;
  50. }
  51. # 输出推送的内容
  52. public function Update(){
  53. $this->observerState = $this->subject->subject_state;
  54. echo "观察者:" .$this->name. "接受到的内容是:" .$this->observerState. "<br/>";
  55. }
  56. }
  57. # 实例化一个频道
  58. $A = new ConcreteSubject();
  59. # 添加两个观察者 - 并加入同一频道
  60. $zs = new ConcreteObserver($A, '张三');
  61. $ls = new ConcreteObserver($A, '李四');
  62. # 让两个观察者获得接受数据推送的权限
  63. $A->Attach($zs);
  64. $A->Attach($ls);
  65. # 注入推送内容
  66. $A->subject_state = "I Love You 小黄牛!";
  67. # 推送消息
  68. $A->Notify();

浏览器输出

  1. 观察者:张三接受到的内容是:I Love You 小黄牛!
  2. 观察者:李四接受到的内容是:I Love You 小黄牛!

观察者模式

  1. 抽象通知者角色(INotifier):定义了通知的接口规则。
  2. 具体通知者角色(Boss):实现抽象通知者的接口,接到状态改变立即向观察者下发通知。
  3. 抽象观察者角色(IObserver):定义接到通知后所做的操作(Update)接口规则。
  4. 具体观察者角色(JingDong):实现具体操作方法。

应用场景

  1. 订阅信息,消息推送

优点

  1. 1、一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  2. 2、一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  3. 3、一个对象必须通知其他对象,而并不知道这些对象是谁。需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。