zoukankan      html  css  js  c++  java
  • 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)
  • 相关阅读:
    组装query,query汇总,query字段
    POJ 1276, Cash Machine
    POJ 1129, Channel Allocation
    POJ 2531, Network Saboteur
    POJ 1837, Balance
    POJ 3278, Catch That Cow
    POJ 2676, Sudoku
    POJ 3126, Prime Path
    POJ 3414, Pots
    POJ 1426, Find The Multiple
  • 原文地址:https://www.cnblogs.com/kelsen/p/3791761.html
Copyright © 2011-2022 走看看