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如何编写易读的代码
Jul 10 PHP
php表单转换textarea换行符的方法
Sep 10 PHP
写php分页时出现的Fatal error的解决方法
Apr 18 PHP
php模拟socket一次连接,多次发送数据的实现代码
Jul 26 PHP
PHP获取windows登录用户名的方法
Jun 24 PHP
国产PHP开发框架myqee新手快速入门教程
Jul 14 PHP
destoon实现调用图文新闻的方法
Aug 21 PHP
PHP利用MySQL保存session的实现思路及示例代码
Sep 09 PHP
php动态函数调用方法
May 21 PHP
使用正则去除php代码中的注释方法
Nov 03 PHP
PHP针对redis常用操作实例详解
Aug 17 PHP
php+mysql+ajax 局部刷新点赞/取消点赞功能(每个账号只点赞一次)
Jul 24 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个人网站架设连环讲(三)
2006/10/09 PHP
PHP实现图片简单上传
2006/10/09 PHP
PHP foreach循环使用详解与实例代码
2010/05/08 PHP
php中最简单的字符串匹配算法
2014/12/16 PHP
ThinkPHP5.1验证码功能实现的示例代码
2020/06/08 PHP
用javascript实现兼容IE7的类库 IE7_0_9.zip提供下载
2007/08/08 Javascript
jquery高级编程的最佳实践详解
2014/03/23 Javascript
nodejs教程之制作一个简单的文章发布系统
2014/11/21 NodeJs
js window对象属性和方法相关资料整理
2015/11/11 Javascript
用JS动态改变表单form里的action值属性的两种方法
2016/05/25 Javascript
浅谈bootstrap源码分析之tab(选项卡)
2016/06/06 Javascript
原生的强大DOM选择器querySelector介绍
2016/12/21 Javascript
Vue实例简单方法介绍
2017/01/20 Javascript
微信小程序 下拉菜单简单实例
2017/04/13 Javascript
使用原生js写ajax实例(推荐)
2017/05/31 Javascript
薪资那么高的Web前端必看书单
2017/10/13 Javascript
react高阶组件添加和删除props
2019/04/26 Javascript
vue中@change兼容问题详解
2019/10/25 Javascript
微信小程序商品详情页底部弹出框
2019/11/22 Javascript
让IDE识别webpack的别名alias的实现方法
2020/05/06 Javascript
Python实现的简单算术游戏实例
2015/05/26 Python
Python实现比较两个列表(list)范围
2015/06/12 Python
python入门教程之识别验证码
2017/03/04 Python
详解python中的数据类型和控制流
2019/08/08 Python
python 串口读取+存储+输出处理实例
2019/12/26 Python
Expedia马来西亚旅游网站:廉价酒店,度假村和航班预订
2016/07/26 全球购物
美国汽车轮胎和轮毂销售网站:Tire Rack
2018/01/11 全球购物
Belvilla德国:在线预订度假屋
2018/04/10 全球购物
房屋改造计划书
2014/01/10 职场文书
档案接收函范文
2014/01/10 职场文书
人民教师的自我评价分享
2014/02/21 职场文书
2014年煤矿工人工作总结
2014/12/08 职场文书
检讨书怎么写
2015/05/07 职场文书
《窃读记》教学反思
2016/02/18 职场文书
Python+OpenCV实现图片中的圆形检测
2022/04/07 Python
nginx 添加http_stub_status_module模块
2022/05/25 Servers