zoukankan      html  css  js  c++  java
  • 观察者模式

    设计原则:

    在观察者模式中,会改变的是主题的状态以及观察者的数目。用这个模式,你可以改变依赖于主题状态的对象,却不必改变主题。——找出程序中会变化的方面,然后将其和固定不变的方面相分离!
     
     主题和观察者都使用接口:观察者利用主题的接口向主题注册,而主题利用观察者接口通知观察者。这样可以让两者之间运作正常,又同时具有松耦合的优点! ——针对接口编程,不针对实现编程!
     观察者模式利用“组合”将许多观察者组合进主题中。对象(观察者——主题)之间的这种关系不是通过继承产生的,而是在运行时利用组合的方式产生的。 ——多用组合,少用继承!
    <?php
     
    class Paper{ /* 主题    */
        private $_observers = array();
     
        public function register($sub){ /*  注册观察者 */
            $this->_observers[] = $sub;
        }
     
         
        public function trigger(){  /*  外部统一访问    */
            if(!empty($this->_observers)){
                foreach($this->_observers as $observer){
                    $observer->update();
                }
            }
        }
    }
     
    /**
     * 观察者要实现的接口
     */
    interface Observerable{
        public function update();
    }
     
    class Subscriber implements Observerable{
        public function update(){
            echo "Callback
    ";
        }
    }
     
    
    下面是测试代码
    
    /*  测试    */
    $paper = new Paper();
    $paper->register(new Subscriber());
    //$paper->register(new Subscriber1());
    //$paper->register(new Subscriber2());
    $paper->trigger();

    这个是比较浅显易懂的。PHP的SPL(standard php library)提供了两个接口来实现观察者模式;

    The SplSubject interface(http://php.net/manual/en/class.splsubject.php)

    The SplObserver interface(http://php.net/manual/en/class.splobserver.php)

    手册上的例子:

    <?php
    
    /**
    * Subject,that who makes news
    */
    class Newspaper implements SplSubject{
        private $name;
        private $observers = array();
        private $content;
        
        public function __construct($name) {
            $this->name = $name;
        }
    
        //add observer
        public function attach(SplObserver $observer) {
            $this->observers[] = $observer;
        }
        
        //remove observer
        public function detach(SplObserver $observer) {
            
            $key = array_search($observer,$this->observers, true);
            if($key){
                unset($this->observers[$key]);
            }
        }
        
        //set breakouts news
        public function breakOutNews($content) {
            $this->content = $content;
            $this->notify();
        }
        
        public function getContent() {
            return $this->content." ({$this->name})";
        }
        
        //notify observers(or some of them)
        public function notify() {
            foreach ($this->observers as $value) {
                $value->update($this);
            }
        }
    }
    
    /**
    * Observer,that who recieves news
    */
    class Reader implements SplObserver{
        private $name;
        
        public function __construct($name) {
            $this->name = $name;
        }
        
        public function update(SplSubject $subject) {
            echo $this->name.' is reading breakout news <b>'.$subject->getContent().'</b><br>';
        }
    }
    
    $newspaper = new Newspaper('Newyork Times');
    
    $allen = new Reader('Allen');
    $jim = new Reader('Jim');
    $linda = new Reader('Linda');
    
    //add reader
    $newspaper->attach($allen);
    $newspaper->attach($jim);
    $newspaper->attach($linda);
    
    //remove reader
    $newspaper->detach($linda);
    
    //set break outs
    $newspaper->breakOutNews('USA break down!');
    
    //=====output======
    //Allen is reading breakout news USA break down! (Newyork Times)
    //Jim is reading breakout news USA break down! (Newyork Times)

      当新对象要填入的时候,只需要在主题(又叫可观察者)中进行注册(注册方式很多,你也可以在构造的时候,或者框架访问的接口中进行注册),然后实现代码直接在新对象的接口中进行。这降低了主题对象和观察者对象的耦合度。

  • 相关阅读:
    六. numpy数据矩阵
    十一.python面向对象(接口)abstractmethod,ABCMeta
    十.python面向对象(itme)
    九.python面向对象(双下方法内置方法)
    八. python面向对象(反射和内置方法)
    七. python面向对象(组合)
    六. python面向对象(内置函数)
    五. python面向对象(多态 和metaclass=abc.ABCMeta)
    四. python面向对象(继承)
    三. python面向对象(私有属性和私有方法 私有静态方法 私有类方法)
  • 原文地址:https://www.cnblogs.com/mingaixin/p/4335700.html
Copyright © 2011-2022 走看看