PHP 的观察者模式(Observer Pattern)

    面向过程编程(结构化编程),我们强调的是程序的分块结构和流程处理。进入面向对象(OOP)编程领域之后,设计模式成为一项很重要的技术。设计模式处理的是对象的生成及其协作、依赖、耦合等等关系问题。比如,单例模式保证一个类只能被实例化一次,工厂模式可以依据不同的条件生成相应的类的实例(对象)。而观察者模式则一般用来实现“事件”处理,构造软件的事件处理系统。

    关于观察者模式(Observer)的实现方法,本人在一篇博客文章中论及过(http://blog.why100000.com/?p=744)。但实际上,PHP5.0 以后,SPL(标准PHP库)提供了方便的对观察者模式的支持,特别是 PHP5.2 以后,SPL 的功能得到了很大的扩充。

    观察者模式涉及到两种(两个或多个)类,一个作为被观察对象(subject),另一个作为“观察者”(Observer)。观察者类监视一个或多个观察对象的状态,当其状态变化时,观察者会得到通知。

    为了支持观察者模式,SPL 提供了 SplSubject 和 SplObserver 接口。

    SplSubject 接口提供了 attach()、detach()、notify() 三个方法。而 SplObserver 接口则提供了 update()方法。

    SplSubject 派生类维护了一个状态,当状态发生变化时 - 比如属性变化等,就会调用 notify() 方法,这时,之前在 attach() 方法中注册的所有 SplObserver 实例的 update() 方法就会被调用。

    class SubjectDemo implements SplSubject
    {
      private $observers, $value;

      public function __construct()
      {
        //$observers被声明为数组,表示观察者可以有多个
        $this->observers = array();
      }

      public function attach(SplObserver $observer)
      {
        $this->observers[] = $observer;
      }

      public function detach(SplObserver $observer)
      {
        if($idx = array_search($observer, $this->observers, true))
          unset($this->observers[$idx]);
      }

      public function notify()
      {
        foreach($this->observers as $observer)
          $observer->update($this);
      }

      public function setValue($value)
      {
        $this->value = $value;
        $this->notify();
      }

      public function getValue()
      {
        return $this->value;
      }

      public function getObserversNumber()
      {
        return count($this->observers);
      }
    }

    class ObserverDemo1 implements SplObserver
    {
      public function update(SplSubject $subject)
      {
        echo 'The new value is '. $subject->getValue() . '<br>';
      }
    }

    class ObserverDemo2 implements SplObserver
    {
      public function update(SplSubject $subject)
      {
        echo 'The Number of Observer(s) is(are) '. $subject->getObserversNumber() . '<br>';
      }
    }

    $subject = new SubjectDemo();

    $observer1 = new ObserverDemo1();
    $observer2 = new ObserverDemo2();

    $subject->attach($observer1);
    $subject->attach($observer2);

    $subject->setValue(100);

    从以上代码中看出,观察者可以有多个类。
    当 $subject 对象的 setValue() 方法被调用(触发)时,本身被作为参数传递到 $observer1 和 $observer2 对象的 update() 方法中使用。所有观察者的 update() 函数类似事件处理函数。
    要扩展事件处理能力,只要从 SplObserver 接口派生一个子类,编写其 update() 函数代码,并附加(attach)到 $subject 对象中即可。

    具体到以上代码,有一个缺陷,就是没有实现不同的事件,用其对应的类来处理。这个不是观察者模式本身的问题,需要结合别的模式来解决。

    作者:张庆(网眼) 西安 PHP 教育培训中心 2010-7-6
    来自“网眼视界”:http://blog.why100000.com
    作者微博:http://t.qq.com/zhangking
    “十万个为什么”电脑学习网:http://www.why100000.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值