• PHP 高级编程(3/5)


    SPL(标准PHP库 - Standard PHP Library)是PHP5面向对象功能中重要的部分。原文解释是这样的“The Standard PHP Library (SPL) is a collection of interfaces and classes that are meant to solve common problems”。

    SplSubject 和 SplObserver 接口

    The SplSubject interface is used alongside SplObserver to implement the Observer Design Pattern.

    观察者模式是一种简单的事件系统,包含了两个或更多的互相交互的类。这一模式允许某个类观察另一个类的状态,当被观察类的状态发生变化时,这个模式会得到通知。被观察的类叫subject,负责观察的类叫做Observer 。PHP 提供的 SplSubject 和 SplObserver接口可用来表达这些内容。

    SplSubject {
    /* 方法 */
    abstract public void attach ( SplObserver $observer )
    abstract public void detach ( SplObserver $observer )
    abstract public void notify ( void )
    }
    SplObserver {
    /* 方法 */
    abstract public void update ( SplSubject $subject )
    }

    这里,splsubject类维护了一个特定状态,当这个状态发生变化时,他就会调用notify方法,所以之前使用attach注册的splobserver实例的update就会被调用。这里我们实现一个简单地观察者模式的例子

    <?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)

    上例中我们通过数组存储 observer对象,使用数组及可能会出现两个问题:

    1、同一个observer可能会被加载多次,导致多次调用同一个对象的update方法。

    2、detach中需要通过迭代或者搜索数组来找到要删除的observer对象,导致运行效率降低。

    SplObjectStorage类

    PHP5提供了SplObjectStorage类,在这里我们可以用来存储observer对象,SplObjectStoraged的实例就像一个数组,但是他所存放的对象是唯一的。SplObjectStorage还可以使用detach直接从集合中删除指定的对象而不用遍历或搜索整个集合。下面看一个SplObjectStorage的例子:

    <?php
    
     $ObjectStorage = new SplObjectStorage();
    
     class classa
     {
         #code...
     }
    
     class classb
     {
        #code...
     }
    
    $a = new classa();
    $b = new classb();
    
    $ObjectStorage->attach($a);
    $ObjectStorage->attach($b);
    $ObjectStorage->attach($a);
    
    
    foreach ($ObjectStorage as $key => $item) {
        echo ($key+1).''.(new ReflectionClass($item))->getName()."
    ";
    }
    

    //output

      1、classa
      2、classb
      [Finished in 0.1s]

    ?>

    上例中我们可以看到,在ObjectStorage这个集合中只有1个calssa,尽管我们添加了两次。并且冲集合中删除一个元素也变得极为简单,拿上面的代码来说,只需使用$ObjectStorage->attach($a);即可轻松的将$a从集合中移除。

    结合 SplObjectStorage 我们再来修改最上面那个观察者模式的例子

    <?php
    /**
     * Subject,that who makes news
     */
    class Newspaper implements SplSubject{
        private $name;
        private $observers;
        private $content;
        
        public function __construct($name) {
            $this->name = $name;
            $this->observers = new SplObjectStorage();
        }
    
        //add observer
        public function attach(SplObserver $observer) {
            $this->observers -> attach($observer);
        }
        
        //remove observer
        public function detach(SplObserver $observer) {
            $this->observers -> detach($observer);
        }
        
        //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 '.$subject->getContent()."
    ";
        }
    }
    
    $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)
  • 相关阅读:
    SpringBoot,来实现MySQL读写分离技术
    range范围
    tuple元组
    序列通用操作及可变序列通用操作
    list列表
    数据
    python基础知识
    charm写代码时添加快捷键
    2、添加到项目里 在⚙图标里选择Add Remote...charm初期设置(远程服务器)
    5、优化
  • 原文地址:https://www.cnblogs.com/kelsen/p/3791761.html
Copyright © 2020-2023  润新知