PHP 观察者模式 的真正实现

1.不是示例代码,而是实际应用代码.
2.多个观察者,多个被观察者
3.根据业务情况,观察者与被观察者都是单例的. 统称为 业务逻辑处理单元(Unit)

1.先实现 处理单元的基类 ,主要实现单例
/**
 * 所有业务逻辑处理单元的基类,实现了单例化
 * @author bluehire
 *
 */
class SUnit {
    
    /**
     * 禁止实例化
     */
    protected function __construct(){
    }
    
    /**
     * 获取本类单例的方法,公开
     *
     * @return SUnit
     */
    public static function instance() {
        //延迟绑定的句柄,子类单例,而不是基类
        if(static::$handle){
            return static::$handle;
        }
        
        //这个是延迟绑定的,运行时的子类的类名
        $class = get_called_class();
        static::$handle = new $class();
        return static::$handle;
    }
}

2.现具体实现一个 观察者(以日志为例,这个是最常用的,而且足够简单)
  这里对普通观察者进行了一次扩展,允许带一个参数
  原因解释一下:  同一个被观察者可能在业务的不同阶段通知同一个观察者,  我想明确告知 观察者 当前阶段之类的信息,
   本来可以用被观察者对象的属性来实现,但感觉太绕了,不明确.
/**
 * 文本日志处理单元,观察者模式
 * @author bluehire
 *
 */
class ULog extends SUnit implements SplObserver {
    protected static $handle; //单例句柄
    
    /**
     * 得到了被观察者的一个通知
     * @see SplObserver::update()
     */
    public function update(SplSubject $object,$params=null){
        //需要被观察者提供一个日志文件名
        $file=$object->getLogFile($params);
        
        //需要被观察者提供一个日志内容
        $msg=$object->getLogMsg($params);
        
        //具体干活
        writeLog($file, $msg);    
    }
}


3.根据以上,如果一个被观察者 要想 被  日志观察者 观察(这话可真费劲), 就要实现两个方法,  所以,这就导致了一个接口
/**
 * 所有需要日志观察者的被观察者要实现的接口
 * @author bluehire
 *
 */
interface ILogSubject extends SplSubject{
    /**
     * 要提供日志文件名
     */
    public function getLogFile($params=null);
    
    /**
     * 要提供日志内容
     */
    public function getLogMsg($params=null);
}

4.现在终于轮到 被观察者了, 所有被观察者都有三个 固定方法,我实现到基类中
/**
 * 被观察者(观察者设计模式)的基类,父类为业务逻辑处理单元(实现了单例化)
 * @author bluehire
 *
 */
class SSubject extends SUnit{
    //当前被观察者的所有观察者
    private $observers=array();
    
    /**
     * 增加一个观察者
     * @param SplObserver $observer
     * @return SSubject
     */
    public function attach(SplObserver $observer){
        $this->observers[]=$observer;
        return $this;
    }
    
    /**
     * 取消一个观察者,这个不常用
     * @param SplObserver $observer
     * @return SSubject
     */
    public function detach(SplObserver $observer){
        $idx = array_search ( $observer, $this->observers, true );
        if ($idx) {
            unset ( $this->observers [$idx] );
        }
        return $this;
    }
    
    /**
     * 通知所有观察者
     * @param 可以带一个参数,发送给所有观察者,观察者会将此参数用于回调被观察者的方法
     * @return SSubject
     */
    public function notify($params=null){
        foreach ( $this->observers as $observer ) {
            $observer->update ( $this,$params );
        }
        return $this;
    }
}

5.开始具体的被观察者,以订单为例
/**
 * 订单处理单元,作为 被观察者
 * @author bluehire
 *
 */
class UOrder extends SSubject implements ILogSubject{
    protected static $handle; //单例句柄
    
    /**
     * 单例,
     * @see SUnit::instance()
     * @return UOrder
     */
    public static function instance(){
        //附加文本日志观察者
        parent::instance()->attach(ULog::instance());
        return self::$handle;
    }
    
    //所有观察者
    private $observers=array();
    
    /**
     * 为日志观察者提供日志文件名
     * @see ILogSubject::getLogFile()
     */
    public function getLogFile($params=null){
        return 'order';
    }
    
    /**
     * 为日志观察者提供日志内容
     * @see ILogSubject::getLogMsg()
     */
    public function getLogMsg($params=null){
        return $params;
    }
    
    
    
    public function something(){
        //......
        $this->notify(array('a'=>1));
    }
}

以上程序实测通过,部分代码请自行修改(如dump,writeLog),

现在说适用范围: 设计 模式这东西,绝对不是随便就可以用的, 简单业务逻辑使用这东西就是个找死.我这里也是因为业务复杂到应该使用一部分设计模式
多个观察者,多个被观察者 才需要使用这个模式 ,


未完事项: 我仍在纠结,要不要使用观察者模式, 相比 过程化的消息通知机制(  被观察者 逐个 通知 观察者,使用 设计 好的 接口), 体会不到好处.

欢迎讨论 Q:31008088



阅读(92) | 评论(0) | 转发(0) |
0

上一篇:晒一下我闺女的书单 四年来总结

下一篇:将博客搬至CSDN

相关热门文章
  • 根据不同的情况
  • 物联网是一个时代的概念...
  • android-- A10开发板--Tslib ...
  • 如何开启VMware串口
  • 策划可行性电子邮件营销方案技...
  • phpStudy 2013下载,PHP5开发...
  • 草和谐榴社区caoliushequ...
  • 灵芝的种类和图片
  • 为PHP添加GD库支持
  • 赤灵芝和黑灵芝的功效区别...
  • LNMP 老是会出现502?
  • suse 运用一个shell获取本机和...
  • 虚拟机 unix 配置ip
  • hp-un 主机新系统读不到磁盘阵...
  • mysql出现问题:Starting MySQ...
给主人留下些什么吧!~~
评论热议

你可能感兴趣的:(PHP)