PHP设计模式之观察者模式

感觉symfony中使用的service机制,依赖注入机制不是被很好的理解,主要是设计模式不了解,于是网上看了一下观察者模式的说明,算是有些了解了。

所谓观察者模式,就是当前对象应当有一个或者若干个观察者,当自己被改变时会通知观察者,让观察者做出反应,如果不用观察者模式,这个“做出反应”可能就是自己去实现的,这样使得代码耦合性太高,把这个反应放入到观察者,让观察者做自己的处理,当前类只专注于自己的业务处理,能有效降低耦合度。


还好PHP自带SPL,standard PHP library,其中就有观察者模式需要用到的接口SplSubject, SplObserver,下面介绍这两个接口。

SplSubject的定义,需要应用观察者模式的类必须实现此接口

SplSubject {

    /* attach用于添加观察者,参数为SplObserver 对象 */
    abstract public void attach ( SplObserver $observer )

    /* attach用于接触观察者,参数为SplObserver 对象 */
    abstract public void detach ( SplObserver $observer )

    /* 用于向观察者发送通知 */
    abstract public void notify ( void )
}

SplObserver 的定义,观察者接口

SplObserver {
         /* SplSubject被修改时需要执行的操作 */
         abstract public void update ( SplSubject $subject )
}

下面是示例代码:

class User implements \SplSubject
{

    protected $data = array();

    protected $observers;

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

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

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

    public function notify()
    {
        /** @var \SplObserver $observer 这里不一定要通知所有的观察者 */
        foreach ($this->observers as $observer) {
            $observer->update($this);
        }
    }

    public function __set($name, $value)
    {
        $this->data[$name] = $value;
        // 通知观察者用户被改变
        $this->notify();
    }
}

简单解释:User类实现了SplSubject接口,并且实现了约定的attach,detach,notify三个方法,然后User类中有一个__set()魔术方法,当通过魔术方法给兑现添加属性时会通知User的观察者,观察者于是会执行update方法,上面的类中attach,detach两个方法比较特别,因为他们的参数是一个对象,这个对象其实就是我们说的观察者,下面看看这个观察者是如何定义的:

class UserObserver implements \SplObserver
{
    /**
     * 观察者要实现的唯一方法
     * 也是被 Subject 调用的方法
     *
     * @param \SplSubject $subject
     */
    public function update(\SplSubject $subject)
    {
        echo get_class($subject) . ' has been updated';
    }
}

这个观察者有一个upate方法,是实现的SqlObserver中的update方法,现在观察者模式就搭建好了,下面开始用这个观察者模式搭建起来的结构:

$user = new User();
$user->attach(new UserObserver );
$user->name = 'jake';

以上实现一个User对象,并添加一个观察者,然后给他赋值会执行set方法,set方法通知自己的观察者,观察者通过update做出了反应。

发表评论

电子邮件地址不会被公开。 必填项已用*标注