+ -
当前位置:首页 → 问答吧 → 使用SPL内置接口,实现观察者模式(Observer Pattern)

使用SPL内置接口,实现观察者模式(Observer Pattern)

时间:2006-11-15

来源:互联网

观察者模式,引用GoF的话来说:
引用:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖与它的对象都得到通知并被自动更新。
在《Head First Design Patterns》中,举了一个现实生活中订阅报纸的例子来描述观察者模式:
报社,相当于观察者模式中的Subject,提供订阅/退订报纸。当新报纸出版时,递送(notify)新报纸到已订阅的用户。用户相当于Observer,
可以自由地订阅(attach)/退订(detach)报纸。当某一用户订阅/退订报纸时,不会影响其他用户。

SPL(Standard PHP Library)从PHP 5.1.0新增了对观察者模式的支持,实际也就是新增了2个内置的接口SplObserver、SplSubject:
复制PHP内容到剪贴板
PHP代码:
interface SplObserver
{
    function update(SplSubject $subject);
}

interface SplSubject
{
    function attach(SplObserver $observer);

    function detach(SplObserver $observer);

    function notify();
}

在IBM的《五种常见的PHP设计模式》中也讲到了观察者模式,我现使用SPL内置的接口,改写了其例子:
复制PHP内容到剪贴板
PHP代码:

<?php
class UserList implements SplSubject
{
    // 观察者们
    private $_observers = array();
    // 用户们
    private $_list = array();
    
    // 绑定一个观察者
    public function attach(SplObserver $observer)
    {
        $this->_observers []= $observer;
    }

    // 解除一个观察者
    public function detach(SplObserver $observer)
    {
        foreach ($this->_observers as $id=>$obs)
        {
            if($obs === $observer)
            {
                unset($this->_observers[$id]);
            }
        }
    }

    // 通知观察者
    public function notify()
    {
        foreach ($this->_observers as $observer)
        {
            $observer->update($this);
        }
    }
    
    //新增用户
    public function addUser($name)
    {
        $this->_list[] = $name;
        $this->notify();
    }
    
    // 获取新增用户
    public function getLatestUser()
    {
        $user = end($this->_list);
        reset($this->_list);
        return $user;
    }
}

class UserListLogger implements SplObserver
{
    public function update(SplSubject $subject)
    {
        $this->log($subject->getLatestUser());
    }
    
    public function log($name)
    {
        echo date('H:i:s') . ', 新增用户' . $name . '<br />';
    }
}

$userList = new UserList();
// 绑定一个观察者:日志记录员
$logger = new UserListLogger();
$userList->attach($logger);

$userList->addUser('Yimin');
//休息2秒
sleep(2);
$userList->addUser('Bantu');

?>

当有新用户增加时,UserList的notify()被调用,notyify()通知所有的观察者,也就是调用了观察者的update方法。在UserListLogger的update方法中,采用的是一种"pull"的方式来获取UserList中的数据(getLatestUser())。

----------
My Blog: Yimin's Blog

作者: Yimin   发布时间: 2006-11-15

支持这种技术文章

作者: 水镜   发布时间: 2006-11-15

引用:
原帖由 水镜 于 2006-11-15 13:54 发表
支持这种技术文章

作者: songwl   发布时间: 2006-11-15

这样会不会好一点?
复制PHP内容到剪贴板
PHP代码:

<?php
class UserList implements SplSubject
{
    // 观察者们
    private $_observers = array();
    // 用户们
    private $_list = array();
    
    // 绑定一个观察者
    public function attach(SplObserver $observer)
    {
        $this->_observers []= $observer;
    }
    // 解除一个观察者
    public function detach(SplObserver $observer)
    {
        foreach ($this->_observers as $id=>$obs)
        {
            if($obs === $observer)
            {
                unset($this->_observers[$id]);
            }
        }
    }
    // 通知观察者
    public function notify()
    {
        foreach ($this->_observers as $observer)
        {
            $observer->update($this);
        }
    }
    
    //新增用户
    public function addUser($name)
    {
        $this->_list[] = $name;
        $this->notify();
    }
    
    // 获取新增用户
    public function getLatestUser()
    {
        $user = end($this->_list);
        reset($this->_list);
        return $user;
    }
}
class UserListLogger implements SplObserver
{
    public function update(SplSubject $subject)
    {
        $this->log($subject->getLatestUser());
    }
    
    public function log($name)
    {
        echo '在'.date('H:i:s') . ', 告诉普通用户,新增用户' . $name . '<br />';
    }
}
//建立管理员
class AdminListLogger implements SplObserver
{
    public function update(SplSubject $subject)
    {
        $this->log($subject->getLatestUser());
    }
    
    public function log($name)
    {
        echo '在'.date('H:i:s') . ', 告诉亲爱的管理员,新增用户' . $name . '<br />';
    }
}
$userList = new UserList();
// 绑定一个观察者:日志记录员
$user = new UserListLogger();
$admin = new AdminListLogger();
$userList->attach($user);
//同时,通知管理员
$userList->attach($admin);
$userList->addUser('Yimin');
//休息2秒
echo '-------------------------<br />';
sleep(2);
$userList->addUser('Bantu');
exit;
?>

作者: flashjay   发布时间: 2008-03-12

热门下载

更多