• PHP设计模式:观察者模式


    示例代码详见https://github.com/52fhy/design_patterns

    观察者模式

    观察者模式(Observer)是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

    观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

    观察者模式UML图:

    观察者模式需要有4个角色:

    • Observer观察者抽象接口,只有一个待实现方法update()
    • 具体观察者(ConcreteObserver)角色:实现了抽象接口,实际应用里可能是日志观察者、短信推送观察者等等;
    • 主题(Subject)抽象类,用于添加观察者、触发观察者;
    • 具体主题的实现类(ConcreteSubject),通过change触发nodifyObservers方法。实际change和nodifyObservers可以合成一个。

    下面以订单为例:当状态变化,需要进行相关处理,例如写日志、短信通知。

    Observer观察者抽象接口:

    namespace YjcObserver;
    
    interface IObserver
    {
        public function update($data);
    }
    

    具体的观察者:

    namespace YjcObserver;
    
    class LogObserver implements IObserver
    {
    
        public function update($data)
        {
            echo 'write log to file.';
        }
    }
    
    class SmsObserver implements IObserver
    {
        public function update($data)
        {
            echo 'send sms';
        }
    }
    

    抽象主题类:

    namespace YjcObserver;
    
    abstract class ISubject
    {
        private  $observers = [];//观察者集合
    
        public function attach(IObserver $observer){
            array_push($this->observers, $observer);
        }
    
        public function detach(IObserver $observer){
            return false;
        }
    
        public function nodifyObservers($data){
            if(count($this->observers) == 0) return false;
            foreach ($this->observers as $observer){
                $observer->update($data);
            }
        }
    
        public abstract function change($data);
    
    }
    

    实现了抽象主题的订单主题:

    namespace YjcObserver;
    
    class OrderSubject extends ISubject
    {
        public function change($data)
        {
            $this->nodifyObservers($data);
        }
    }
    

    测试:

    $order_subject = new OrderSubject();
    $order_subject->attach(new LogObserver());//写日志
    $order_subject->attach(new SmsObserver());//发短信
    $order_subject->change(['oid' => '1', 'flag' => 3]);//订单状态变化,触发观察者
    

    输出:

    write log to file.
    send sms
    

    观察者实际还区分推模型和拉模型。上述讲的是推模型。推模型主动将观察者需要的数据$data通过update()传递过去;而拉模型是主题对象不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值。具体查看:《JAVA与模式》之观察者模式

  • 相关阅读:
    Masonry
    数据解析
    UIImage 两种初始化的区别
    GCD
    数据处理之文件读写
    关注即时通讯
    跳转appStore评分
    iOS 9 Safari广告拦截插件
    Cocoapods的安装以及使用
    iOS中Block的基础用法
  • 原文地址:https://www.cnblogs.com/52fhy/p/7076728.html
Copyright © 2020-2023  润新知