php设计模式之四__观察者模式

来源:互联网 发布:梯度下降算法迭代 编辑:程序博客网 时间:2024/05/31 18:44

观察者模式

1.定义

定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有的观察者对象,使他们能够自动更新自己。

2. UML图


3.代码示例:

<?php/*** 观察者模式* @package design pattern*//*** 抽象主题角色*/interface Subject {    /**     * 增加一个新的观察者对象     * @param Observer $observer     */    public function attach(Observer $observer);    /**     * 删除一个已注册过的观察者对象     * @param Observer $observer     */    public function detach(Observer $observer);    /**     * 通知所有注册过的观察者对象     */    public function notifyObservers();}/*** 具体主题角色*/class ConcreteSubject implements Subject {    private $_observers;    public function __construct() {        $this->_observers = array();    }    /**     * 增加一个新的观察者对象     * @param Observer $observer     */    public function attach(Observer $observer) {        return array_push($this->_observers, $observer);    }    /**     * 删除一个已注册过的观察者对象     * @param Observer $observer     */    public function detach(Observer $observer) {        $index = array_search($observer, $this->_observers);        if ($index === FALSE || ! array_key_exists($index, $this->_observers)) {            return FALSE;        }        unset($this->_observers[$index]);        return TRUE;    }    /**     * 通知所有注册过的观察者对象     */    public function notifyObservers() {        if (!is_array($this->_observers)) {            return FALSE;        }        foreach ($this->_observers as $observer) {            $observer->update();        }        return TRUE;    }}/*** 抽象观察者角色*/interface Observer {    /**     * 更新方法     */    public function update();}class ConcreteObserver implements Observer {    /**     * 观察者的名称     * @var <type>     */    private $_name;    public function __construct($name) {        $this->_name = $name;    }    /**     * 更新方法     */    public function update() {        echo 'Observer', $this->_name, ' has notified.<br />';    }}// 实例化类:$subject = new ConcreteSubject();/* 添加第一个观察者 */$ob1 = new ConcreteObserver('Martin');$subject->attach($ob1);echo '<br /> The First notify:<br />';$subject->notifyObservers();/* 添加第二个观察者 */$ob2 = new ConcreteObserver('phppan');$subject->attach($ob2);echo '<br /> The Second notify:<br />';$subject->notifyObservers();/* 删除第一个观察者 */$subject->detach($ob1);echo '<br /> The Third notify:<br />';$subject->notifyObservers();
4. 具体示例:

 <?php /**    *php内部的支持  *        SplSubject 接口,它代表着被观察的对象,  *        其结构:  *        interface SplSubject  *        {  *            public function attach(SplObserver $observer);  *            public function detach(SplObserver $observer);  *            public function notify();  *        }  *        SplObserver 接口,它代表着充当观察者的对象,  *        其结构:  *        interface SplObserver  *        {     *            public function update(SplSubject $subject);  *        }  */ /**  * 用户登陆-诠释观察者模式  */class Subject implements SplSubject{      private $observers = array();      //订阅    public function attach(SplObserver $observer)    {          if (!in_array($observer,$this->observers)) {              $this->observers[] = $observer;          }      }    //取消订阅    public function detach(SplObserver $observer)      {          if (false != ($index = array_search($observer, $this->observers))) {              unset($this->observers[$index]);          }      }    public function post()      {          //post相关code          $this->notify();      }        public function notify()      {          foreach ($this->observers as $observer) {              $observer->update($this);          }      }        public function setCount($count)      {          echo "数据量加" . $count."<br>";      }      public function setIntegral($integral)      {           echo "积分量加" . $integral."<br>";      }  }   //观察者class Observer1 implements SplObserver{      public function update(SplSubject $subject)      {          $subject-> setCount(1);      }  }  class Observer2 implements SplObserver{      public function update(SplSubject $subject)      {          $subject-> setIntegral(10);      }  }    //test case  $subject = new Subject();  $subject->attach(new Observer1());  $subject->attach(new Observer2());  $subject->post();
5.适用情况

a.一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。

b.一个对象必须通知其他对象,而并不知道这些对象是谁。需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

6.不足

当观察者类被完全封装后,无法通过改修改类来实现对主题改变的观察,此时,观察者和主题之间相互不知道。此时可以通过委托的方式来解决此问题。


1 0