PHP设计模式之迭代器模式的深入解析


Posted in PHP onJune 13, 2013

迭代器(Iterator)模式,它在一个很常见的过程上提供了一个抽象:位于对象图不明部分的一组对象(或标量)集合上的迭代。迭代有几种不同的具体执行方法:在数组属性,集合对象,数组,甚至一个查询结果集之上迭代。

在对象的世界里,迭代器模式要维持类似数组的功能,看作是一个非侵入性对象刻面(facet),Client类往往分离自真实对象实现,指iterator接口。只要有可能,我们可以给迭代器传送一个引用,代替将来可能发生变化的具体或抽象类。
PHP设计模式之迭代器模式的深入解析
参与者:
◆客户端(Client):
引用迭代器模式的方法在一组值或对象上执行一个循环。
◆迭代器(Iterator):在迭代过程上的抽象,包括next(),isFinished(),current()等方法。
◆具体迭代器(ConcreteIterators):在一个特定的对象集,如数组,树,组合,集合等上实现迭代。
通过Traversable接口,PHP原生态支持迭代器模式,这个接口由Iterator和IteratorAggregate做了扩展,这两个子接口不仅是定义了一套标准的方法,每个Traversable对象都可以原封不动地传递给foreach(),foreach是迭代器的主要客户端,Iterator实现是真正的迭代器,而IteratorAggregate是有其它职责的Traversable对象,它通过getIterator()方法返回一个Iterator。

PHP设计模式之迭代器模式的深入解析

标准PHP库是PHP中绑定的唯一通用目的面向对象库,定义了额外的接口和公用类。OuterIterator实现装饰一个Iterator,CachingIterator和LimitIterator是这个接口的两个例子。

RecursiveIterator是Iterator接口为树形结构实现的一个扩展,它定义了一组额外的方法检查迭代中当前元素的子对象是否存在。RecursiveArrayIterator和RecursiveDirectoryIterator是这个接口的实现示例,这些类型的迭代器可以原样使用,或是用一个RecursiveIteratorIterator桥接到一个普通的迭代器契约。这个OuterIterator实现将会根据构造参数执行深度优先或广度优先遍历。

使用RecursiveIteratorIterator时,可以将其传递给foreach,请看后面的代码示例,了解RecursiveIterators的不同用法和它们的超集Iterator。最后,SeekableIterators向契约添加了一个seek()方法,它可以用于移动Iterator的内部状态到一个特定的迭代点。 

注意,迭代器是比对象集更好的抽象,因为我们可以让InfiniteIterators,NoRewindIterators等,不用与普通数组阵列一致,因此,Iterator缺少count()函数等功能。

在PHP官方手册中可以找到完整的SPL迭代器列表。得益于对PHP的强力支持,使用迭代器模式的大部分工作都包括在标准实现中,下面的代码示例就利用了标准Iterator和RecursiveIterators的功能。

    <?php 
    /**  
     * Collection that wraps a numeric array.  
     * All five public methods are needed to implement  
     * the Iterator interface.  
     */  
    class Collection implements Iterator  
    {  
 private $_content;  
 private $_index = 0;   public function __construct(array $content)  
 {  
     $this->_content = $content;  
 }  
 public function rewind()  
 {  
     $this->_index = 0;  
 }  
 public function valid()  
 {  
     return isset($this->_content[$this->_index]);  
 }  
 public function current()  
 {  
     return $this->_content[$this->_index];  
 }  
 public function key()  
 {  
     return $this->_index;  
 }  
 public function next()  
 {  
     $this->_index++;  
 }  
    }  
    $array = array('A', 'B', 'C', 'D');  
    echo "Collection: ";  
    foreach (new Collection($array) as $key => $value) {  
 echo "$key => $value. ";  
    }  
    echo "\n"; 
    /**  
     * Usually IteratorAggregate is the interface to implement.  
     * It has only one method, which must return an Iterator  
     * already defined as another class (e.g. ArrayIterator)  
     * Iterator gives a finer control over the algorithm,  
     * because all the hook points of Iterator' contract  
     * are available for implementation.  
     */  
    class NumbersSet implements IteratorAggregate  
    {  
 private $_content;  
 public function __construct(array $content)  
 {  
     $this->_content = $content;  
 }  
 public function contains($number)  
 {  
     return in_array($number, $this->_content);  
 }  
 /**  
  * Only this method is necessary to implement IteratorAggregate.  
  * @return Iterator  
  */  
 public function getIterator()  
 {  
     return new ArrayIterator($this->_content);  
 }  
    }  
    echo "NumbersSet: ";  
    foreach (new NumbersSet($array) as $key => $value) {  
 echo "$key => $value. ";  
    }  
    echo "\n"; 
    // let's play with RecursiveIterator implementations  
    $it = new RecursiveArrayIterator(array(  
 'A',  
 'B',  
 array(  
     'C',  
     'D'  
 ),  
 array(  
     array(  
  'E',  
  'F'  
     ),  
     array(  
  'G',  
  'H',  
  'I'  
     )  
 )  
    ));  
    // $it is a RecursiveIterator but also an Iterator,  
    // so it loops normally over the four elements  
    // of the array.  
    echo "Foreach over a RecursiveIterator: ";  
    foreach ($it as $value) {  
 echo $value;  
 // but RecursiveIterators specify additional  
 // methods to explore children nodes  
 $children = $it->hasChildren() ? '{Yes}' : '{No}';  
 echo $children, ' ';  
    }  
    echo "\n";  
    // we can bridge it to a different contract via  
    // a RecursiveIteratorIterator, whose cryptic name  
    // should be read as 'an Iterator that spans over  
    // a RecursiveIterator'.  
    echo "Foreach over a RecursiveIteratorIterator: ";  
    foreach (new RecursiveIteratorIterator($it) as $value) {  
 echo $value;  
    }  
    echo "\n";
PHP 相关文章推荐
使用php+xslt在windows平台上
Oct 09 PHP
将OICQ数据转成MYSQL数据
Oct 09 PHP
PHP分页函数代码(简单实用型)
Dec 02 PHP
php实现图片上传并进行替换操作
Mar 15 PHP
php实现XML和数组的相互转化功能示例
Feb 08 PHP
PHP设计模式之装饰器模式实例详解
Feb 07 PHP
ThinkPHP实现的rsa非对称加密类示例
May 29 PHP
win7 wamp 64位 php环境开启curl服务遇到的问题及解决方法
Sep 16 PHP
php二维数组按某个键值排序的实例讲解
Feb 15 PHP
PHP设计模式(五)适配器模式Adapter实例详解【结构型】
May 02 PHP
PHP实现简单注册登录系统
Dec 28 PHP
PHP实现rar解压读取扩展包小结
Jun 03 PHP
PHP设计模式之解释器模式的深入解析
Jun 13 #PHP
PHP设计模式之代理模式的深入解析
Jun 13 #PHP
PHP设计模式之责任链模式的深入解析
Jun 13 #PHP
PHP设计模式之结构模式的深入解析
Jun 13 #PHP
PHP设计模式之命令模式的深入解析
Jun 13 #PHP
深入Memcache的Session数据的多服务器共享详解
Jun 13 #PHP
探讨:如何使用PHP实现计算两个日期间隔的年、月、周、日数
Jun 13 #PHP
You might like
简单介绍下 PHP5 中引入的 MYSQLI的用途
2007/03/19 PHP
攻克CakePHP系列一 连接MySQL数据库
2008/10/22 PHP
PHP开发中的错误收集,不定期更新。
2011/02/03 PHP
php使用exec shell命令注入的方法讲解
2013/11/12 PHP
yii中widget的用法
2014/12/03 PHP
php实现中文字符截取防乱码方法汇总
2015/04/29 PHP
php操作路径的经典方法(必看篇)
2016/10/04 PHP
随机显示经典句子或诗歌的javascript脚本
2007/08/04 Javascript
window.onload 加载完毕的问题及解决方案(上)
2009/07/09 Javascript
cookie的secure属性详解
2015/04/08 Javascript
jquery实现鼠标滑过小图查看大图的方法
2015/07/20 Javascript
JS验证逗号隔开可以是中文字母数字
2016/04/22 Javascript
浅谈Node.js:fs文件系统模块
2016/12/08 Javascript
js实现简单的二级联动效果
2017/03/09 Javascript
JavaScript实现打地鼠小游戏
2020/04/23 Javascript
js轮播图无缝滚动效果
2017/06/17 Javascript
浅谈原生JS中的延迟脚本和异步脚本
2017/07/12 Javascript
浅谈Node.js 中间件模式
2018/06/12 Javascript
ES10 特性的完整指南小结
2019/03/04 Javascript
解决vue+router路由跳转不起作用的一项原因
2020/07/19 Javascript
一文秒懂JavaScript构造函数、实例、原型对象以及原型链
2020/08/25 Javascript
Python os模块中的isfile()和isdir()函数均返回false问题解决方法
2015/02/04 Python
python实现多线程的方式及多条命令并发执行
2016/06/07 Python
Python学习小技巧之列表项的排序
2017/05/20 Python
Python操作Redis之设置key的过期时间实例代码
2018/01/25 Python
python+splinter实现12306网站刷票并自动购票流程
2018/09/25 Python
python3利用Socket实现通信的方法示例
2019/05/06 Python
Python实现的统计文章单词次数功能示例
2019/07/08 Python
Python函数的定义方式与函数参数问题实例分析
2019/12/26 Python
CSS3 3D制作实战案例分析
2016/09/18 HTML / CSS
美国最大的无人机经销商:DroneNerds
2018/03/20 全球购物
应届生会计电算化求职信
2013/10/03 职场文书
安全标准化汇报材料
2014/02/03 职场文书
顶撞老师检讨书
2014/02/07 职场文书
《生命的药方》教学反思
2014/04/08 职场文书
Nginx的基本概念和原理
2022/03/21 Servers