观察者模式

观察者模式

在主要的业务类中通过注册对象来实现功能的分离开发

观察者模式属于行为模式,是定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
当一个对象状态发生改变后,会影响到其他几个对象的改变,这时候可以用观察者模式。
观察者模式符合接口隔离原则,实现了对象之间的松散耦合。

别名

发布-订阅<Subscribe>模式
模型-视图<View>模式
源-收听者<Listener>模式
从属者模式

代码.理解性为主

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: dream
  5. * Date: 2018/10/13
  6. * Time: 下午4:04
  7. * 观察者模式
  8. */
  9. /**
  10. * 定义观察者需要实现的接口
  11. * Interface MsgSend
  12. */
  13. interface MsgSend
  14. {
  15. public function send();
  16. }
  17. /**
  18. * 微信类
  19. * Class Wechat
  20. */
  21. class Wechat implements MsgSend
  22. {
  23. /**
  24. * 微信发送消息功能 业务区
  25. */
  26. public function send()
  27. {
  28. echo "发送微信消息" . PHP_EOL;
  29. }
  30. }
  31. /**
  32. * 短信类
  33. * Class Sms
  34. */
  35. class Sms implements MsgSend
  36. {
  37. /**
  38. * 短信发送功能 业务区
  39. */
  40. public function send()
  41. {
  42. echo "发送短信" . PHP_EOL;
  43. }
  44. }
  45. /**
  46. * 订单支付类 具体根据业务逻辑定,这里只是学习思想
  47. * Class Payafter
  48. */
  49. class Payafter
  50. {
  51. /**
  52. * 观察者实例
  53. * @var array
  54. */
  55. private $_ob = [];
  56. /**
  57. * 注册观察者
  58. * @param $obj
  59. */
  60. public function register($obj)
  61. {
  62. $this->_ob = $obj;
  63. }
  64. /**
  65. * 统一执行方法
  66. */
  67. public function trigger()
  68. {
  69. if (!empty($this->_ob)) {
  70. foreach ($this->_ob as $observe) {
  71. $observe->send();
  72. }
  73. }
  74. }
  75. }
  76. echo "<pre>";
  77. $payafter = new Payafter();
  78. $payafter->register([new Wechat(), new Sms()]);
  79. $payafter->trigger();
  80. //测试结果,当触发动作:
  81. //发送微信消息
  82. //发送短信

在PHP SPL中已经提供SplSubject和SqlOberver接口,可以根据这个自建观察者

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: dream
  5. * Date: 2018/10/13
  6. * Time: 下午4:34
  7. * 观察者模式
  8. */
  9. class Subject implements SplSubject
  10. {
  11. /**
  12. * 观察者实例变量
  13. * @var array
  14. */
  15. private $_observers = [];
  16. /**
  17. * 添加观察者实例
  18. * @param SplObserver $observer
  19. */
  20. public function attach(SplObserver $observer)
  21. {
  22. !in_array($observer, $this->_observers) && $this->_observers[] = $observer;
  23. }
  24. /**
  25. * 删除观察者实例
  26. * @param SplObserver $observer
  27. */
  28. public function detach(SplObserver $observer)
  29. {
  30. if (false !== ($index = array_search($observer, $this->_observers))) {
  31. unset($this->_observers[$index]);
  32. }
  33. }
  34. /**
  35. * 实现提示方法即触发方法
  36. */
  37. public function notify()
  38. {
  39. if (!empty($this->_observers)) {
  40. foreach ($this->_observers as $observer) {
  41. $observer->update($this);
  42. }
  43. }
  44. }
  45. /**
  46. * 设置数量
  47. * @param $count
  48. */
  49. public function setCount($count)
  50. {
  51. echo "数据量加" . $count . '<br>';
  52. }
  53. /**
  54. * 设置积分
  55. * @param $integral
  56. */
  57. public function setIntegral($integral)
  58. {
  59. echo "积分量加" . $integral . '<br>';
  60. }
  61. }
  62. /**
  63. * 观察者1
  64. * Class ObserverOne
  65. */
  66. class ObserverOne implements SplObserver
  67. {
  68. public function update(SplSubject $subject)
  69. {
  70. $subject->setCount(10);
  71. }
  72. }
  73. /**
  74. * 观察者2
  75. * Class ObserverTwo
  76. */
  77. class ObserverTwo implements SplObserver
  78. {
  79. public function update(SplSubject $subject)
  80. {
  81. $subject->setIntegral(100);
  82. }
  83. }
  84. /**
  85. * Class Client 客户端 还可以再封装跟需求来
  86. */
  87. class Client
  88. {
  89. /**
  90. * 测试方法
  91. */
  92. public static function test()
  93. {
  94. // 初始化主题
  95. $subject = new Subject();
  96. // 初始化观察者一
  97. $observer1 = new ObserverOne();
  98. // 初始化观察者二
  99. $observer2 = new ObserverTwo();
  100. // 添加观察者一
  101. $subject->attach($observer1);
  102. // 添加观察者二
  103. $subject->attach($observer2);
  104. // 消息提示
  105. $subject->notify();//输出:数据量加1 积分量加10
  106. // 移除观察者一
  107. $subject->detach($observer1);
  108. // 消息提示
  109. $subject->notify();//输出:数据量加1 积分量加10 积分量加10
  110. }
  111. }
  112. // 执行测试
  113. Client::test();
  114. // 测试结果
  115. //数据量加10
  116. //积分量加100
  117. //积分量加100


评论 0

发表评论

Top