PHP 设计模式之观察者模式

来源:互联网 发布:南方报业 知乎 编辑:程序博客网 时间:2024/04/30 06:05
设计原则
 
在观察者模式中,会改变的是主题的状态以及观察者的数目。用这个模式,你可以改变依赖于主题状态的对象,却不必改变主题。——找出程序中会变化的方面,然后将其和固定不变的方面相分离!
 
 主题和观察者都使用接口:观察者利用主题的接口向主题注册,而主题利用观察者接口通知观察者。这样可以让两者之间运作正常,又同时具有松耦合的优点! ——针对接口编程,不针对实现编程!

 观察者模式利用“组合”将许多观察者组合进主题中。对象(观察者——主题)之间的这种关系不是通过继承产生的,而是在运行时利用组合的方式产生的。 ——多用组合,少用继承!
 
代码
<?php/** * 观察者模式 * @author: Mac * @date: 2012/02/22 */  class Paper{ /* 主题    */    private $_observers = array();     public function register($sub){ /*  注册观察者 */        $this->_observers[] = $sub;    }          public function trigger(){  /*  外部统一访问    */        if(!empty($this->_observers)){            foreach($this->_observers as $observer){                $observer->update();            }        }    }} /** * 观察者要实现的接口 */interface Observerable{    public function update();} class Subscriber implements Observerable{    public function update(){        echo "Callback\n";    }}

/*  测试    */$paper = new Paper();$paper->register(new Subscriber());//$paper->register(new Subscriber1());//$paper->register(new Subscriber2());$paper->trigger();



---------------------------------------------------------------------------------------------------------


当一个对象状态发生改变后,会影响到其他几个对象的改变,这时候可以用观察者模式。像wordpress这样的应用程序中,它容外部开发组开发插件,比如用户授权的博客统计插件、积分插件,这时候可以应用观察者模式,先注册这些插件,当用户发布一篇博文后,就回自动通知相应的插件更新。

观察者模式符合接口隔离原则,实现了对象之间的松散耦合。

观察者模式UML图:


在php SPL中已经提供SplSubject和SqlOberver接口

[php] view plaincopy
  1. interface SplSubject  
  2. {  
  3.     function attach(SplObserver $observer);  
  4.     function detach(SplObserver $observer);  
  5.     function notify();  
  6. }  
  7. interface SqlObserver  
  8. {  
  9.     function update(SplSubject $subject);  
  10. }  


下面具体实现上面例子
[php] view plaincopy
  1. class Subject implements SplSubject  
  2. {  
  3.     private $observers;  
  4.   
  5.     public function attach(SplObserver $observer)  
  6.     {  
  7.         if (!in_array($observer$this->observers)) {  
  8.             $this->observers[] = $observer;  
  9.         }  
  10.     }  
  11.   
  12.   
  13.     public function detach(SplObserver $observer)  
  14.     {  
  15.         if (false != ($index = array_search($observer$this->observers))) {  
  16.             unset($this->observers[$index]);  
  17.         }  
  18.     }  
  19.   
  20.     public function post()  
  21.     {  
  22.         //post相关code  
  23.         $this->notify();  
  24.     }  
  25.   
  26.     private function notify()  
  27.     {  
  28.         foreach ($this->observers as $observer) {  
  29.             $observer->update($this);  
  30.         }  
  31.     }  
  32.   
  33.     public function setCount($count)  
  34.     {  
  35.         echo "数据量加" . $count;  
  36.     }  
  37.     public function setIntegral($integral)  
  38.     {  
  39.          echo "积分量加" . $integral;  
  40.     }  
  41.   
  42. }  
  43.   
  44.   
  45. class Observer1 implements SplObserver  
  46. {  
  47.     public function update($subject)  
  48.     {  
  49.         $subject-> setCount(1);  
  50.     }  
  51. }  
  52. class Observer2 implements SplObserver  
  53. {  
  54.     public function update($subject)  
  55.     {  
  56.         $subject-> setIntegral(10);  
  57.     }  
  58. }  
  59.   
  60.   
  61. class Client  
  62. {  
  63.     public  function test()  
  64.     {  
  65.         $subject = new Subject();  
  66.         $subject->attach(new Observer1());  
  67.         $subject->attach(new Observer2());  
  68.         $subject->post();//输出:数据量加1 积分量加10  
  69.     }  
  70. }  







0 0
原创粉丝点击