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 开发工具
Dec 06 PHP
PHP ajax 分页类代码
Nov 13 PHP
php中使用Akismet防止垃圾评论的代码
Jun 10 PHP
使用php shell命令合并图片的代码
Jun 23 PHP
浅析php中如何在有限的内存中读取大文件
Jul 02 PHP
PHP中redis的用法深入解析
Feb 20 PHP
php中http与https跨域共享session的解决方法
Dec 20 PHP
php下Memcached入门实例解析
Jan 05 PHP
PHP内核探索之变量
Dec 22 PHP
php实现购物车功能(以大苹果购物网为例)
Mar 09 PHP
PHP框架Laravel中使用UUID实现数据分表操作示例
May 30 PHP
ThinkPHP5框架实现简单的批量查询功能示例
Jun 07 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
php学习之运算符相关概念
2011/06/09 PHP
php中设置多级目录session的问题
2011/08/08 PHP
Yii框架参数化查询中IN查询只能查询一个的解决方法
2017/05/20 PHP
浅谈Yii乐观锁的使用及原理
2017/07/25 PHP
PHP全局使用Laravel辅助函数dd
2019/12/26 PHP
JS获取scrollHeight问题想到的标准问题
2007/05/27 Javascript
jQuery asp.net 用json格式返回自定义对象
2010/04/07 Javascript
js封装的textarea操作方法集合(兼容很好)
2010/11/16 Javascript
对javascript的一点点认识总结《javascript高级程序设计》读书笔记
2011/11/30 Javascript
了不起的node.js读书笔记之mongodb数据库交互
2014/12/22 Javascript
原生javascript获取元素样式
2014/12/31 Javascript
深入理解JavaScript系列(27):设计模式之建造者模式详解
2015/03/03 Javascript
javascript为按钮注册回车事件(设置默认按钮)的方法
2015/05/09 Javascript
一张Web前端的思维导图分享
2015/07/03 Javascript
使用requestAnimationFrame实现js动画性能好
2015/08/06 Javascript
JS Array.slice 截取数组的实现方法
2016/01/02 Javascript
基于BootStrap Metronic开发框架经验小结【五】Bootstrap File Input文件上传插件的用法详解
2016/05/12 Javascript
jQuery EasyUI基础教程之EasyUI常用组件(推荐)
2016/07/15 Javascript
ES6概念 ymbol.for()方法
2016/12/25 Javascript
详解vue-router 路由元信息
2017/09/13 Javascript
如何在Angular应用中创建包含组件方法示例
2019/03/23 Javascript
解决echarts图表使用v-show控制图表显示不全的问题
2020/07/19 Javascript
在unittest中使用 logging 模块记录测试数据的方法
2018/11/30 Python
浅谈pyqt5中信号与槽的认识
2019/02/17 Python
Django框架模板文件使用及模板文件加载顺序分析
2019/05/23 Python
python twilio模块实现发送手机短信功能
2019/08/02 Python
关于win10在tensorflow的安装及在pycharm中运行步骤详解
2020/03/16 Python
python os模块常用的29种方法使用详解
2020/06/02 Python
Python 实现自动登录+点击+滑动验证功能
2020/06/10 Python
高职助产应届生自荐信
2013/09/24 职场文书
预备党员的自我评价
2014/03/12 职场文书
2014年党员个人工作总结
2014/12/02 职场文书
信访工作个人总结
2015/03/03 职场文书
2016年大学生暑假爱心支教活动策划书
2015/11/26 职场文书
OpenCV-Python实现图像平滑处理操作
2021/06/08 Python
Spring-cloud Config Server的3种配置方式
2021/09/25 Java/Android