06月23, 2016

PHP设计模式——观察者模式

什么是观察者模式

观察者模式是一种一对多的依赖关系,当一个事物的状态发生变化时,这个事物广播通知所有他的观察者们,就是观察者模式。

比如:

  • 一个股票软件,当某一股票跌停时,通知所有关注这个股票的人。
  • 一个报警系统,当有人闯入时,通知主人跑路,通知保安尽快赶来,通知警察来抓人。

举个我们常用的开发例子,

  • 比如一个电商系统,当客户下单成功时,可能需要短信通知用户已下单成功,还要通知客服尽快与客户确认。下面我们用PHP实现这个例子。

用PHP实现观察者模式

实现思路

SPL标准库定义了观察者模式的两个接口,分别如下


//被观察事件需要实现的接口
interface SplSubject  {

    /**
     * Attach an SplObserver
     * @link http://php.net/manual/en/splsubject.attach.php
     * @param SplObserver $observer <p>
 * The <b>SplObserver</b> to attach.
     * </p>
     * @return void 
     * @since 5.1.0
     * 用来添加观察者  
     */
    public function attach (SplObserver $observer);

    /**
     * Detach an observer
     * @link http://php.net/manual/en/splsubject.detach.php
     * @param SplObserver $observer <p>
 * The <b>SplObserver</b> to detach.
     * </p>
     * @return void 
     * @since 5.1.0
     * 用来删除观察者 
     */
    public function detach (SplObserver $observer);

    /**
     * Notify an observer
     * @link http://php.net/manual/en/splsubject.notify.php
     * @return void 
     * @since 5.1.0
     * 通知所有事件
     */
    public function notify ();

}

//观察者需要实现的接口
interface SplObserver  {

    /**
     * Receive update from subject
     * @link http://php.net/manual/en/splobserver.update.php
     * @param SplSubject $subject <p>
 * The <b>SplSubject</b> notifying the observer of an update.
     * </p>
     * @return void 
     * @since 5.1.0
     * 根据事件状态改变
     */
    public function update (SplSubject $subject);

}

实现这两个接口就能用PHP实现观察者模式了,下面的代码我们还需要用到SplObjectStorage对象,顾名思义,他是PHP的一个对象存储器,可以实现对象的添加删除遍历等等。下面贴出实现代码。


class Order implements SplSubject {

    protected $observers = null;

    public $status = 0; //假设状态1为成功付款,0尚未付款

    public function __construct()
    {
        $this->observers = new SplObjectStorage();
    }

    public function paySuccess() {
        $this->status = 1;
        $this->notify();
    }

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

    public function detach (SplObserver $observer) {
        $this->observers->detach($observer);
    }

    public function notify()
    {
        $this->observers->rewind();
        while ($this->observers->valid()) {
            $observer = $this->observers->current();
            $observer->update($this);
            $this->observers->next();
        }
    }

}

class MessageNotify implements SplObserver {

    public function update (SplSubject $subject) {
        if ($subject->status == 1) {
            echo "您好,您的订单成功付款";
        }
    }

}

class RemindSupport implements SplObserver {

    public function update (SplSubject $subject) {
        if ($subject->status == 1) {
            echo "有客户上钩了";
        }
    }

}

$order = new order();
$order->attach(new MessageNotify());
$order->attach(new RemindSupport());
$order->paySuccess();

上述的代码非常简单易懂,订单类实现SplSubject接口,短信通知和客服提醒实现SplObserver接口,订单类里面用SplObjectStorage做观察者对象的存储器,当订单的状态发生变化时,我们遍历存储器,通知里面所有的事件,通知时把自己传进去,让观察者根据状态判断要进行什么的操作。

本文链接:http://www.qiana.info/post/oberver.html

-- EOF --

Comments