zoukankan      html  css  js  c++  java
  • 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与模式》之观察者模式

  • 相关阅读:
    LeetCode 258 Add Digits
    LeetCode 231 Power of Two
    LeetCode 28 Implement strStr()
    LeetCode 26 Remove Duplicates from Sorted Array
    LeetCode 21 Merge Two Sorted Lists
    LeetCode 20 Valid Parentheses
    图形处理函数库 ImageTTFBBox
    php一些函数
    func_get_arg(),func_get_args()和func_num_args()的用法
    人生不是故事,人生是世故,摸爬滚打才不会辜负功名尘土
  • 原文地址:https://www.cnblogs.com/52fhy/p/7076728.html
Copyright © 2011-2022 走看看