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

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

在对象的世界里,迭代器模式要维持类似数组的功能,看作是一个非侵入性对象刻面(facet),Client类往往分离自真实对象实现,指iterator接口。只要有可能,我们可以给迭代器传送一个引用,代替将来可能发生变化的具体或抽象类。

参与者:
◆客户端(Client):
引用迭代器模式的方法在一组值或对象上执行一个循环。
◆迭代器(Iterator):在迭代过程上的抽象,包括next(),isFinished(),current()等方法。
◆具体迭代器(ConcreteIterators):在一个特定的对象集,如数组,树,组合,集合等上实现迭代。
通过Traversable接口,PHP原生态支持迭代器模式,这个接口由Iterator和IteratorAggregate做了扩展,这两个子接口不仅是定义了一套标准的方法,每个Traversable对象都可以原封不动地传递给foreach(),foreach是迭代器的主要客户端,Iterator实现是真正的迭代器,而IteratorAggregate是有其它职责的Traversable对象,它通过getIterator()方法返回一个Iterator。

标准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";

(0)

相关推荐

  • PHP迭代器实现斐波纳契数列的函数

    复制代码 代码如下: class Fibonacci implements Iterator {     private $previous = 1;     private $current = 0;     private $key = 0; public function current() {         return $this->current;     } public function key() {         return $this->key;     } pub

  • php使用递归与迭代实现快速排序示例

    复制代码 代码如下: /** * 递归法实现的快速排序 * @param $seq * @return array */function quicksort($seq){    if (count($seq) > 1) {        $k = $seq[0];        $x = array();        $y = array();        $_size = count($seq); //do not use count($seq) in loop for.        f

  • php可应用于面包屑导航的迭代寻找家谱树实现方法

    本文实例讲述了php可应用于面包屑导航的迭代寻找家谱树实现方法.分享给大家供大家参考.具体实现方法如下: <?php echo "<pre>"; $area = array( array('id'=>1,'area'=>'北京','pid'=>0), array('id'=>2,'area'=>'广西','pid'=>0), array('id'=>3,'area'=>'广东','pid'=>0), array('

  • php5.5中类级别的常量使用介绍

    不久前php刚发布了5.5的第一个稳定版,介绍了一个类级别的常量,名字是 `CLASS` 这个常量对所有的类有效,返回类的全名. 复制代码 代码如下: <?php namespace vendorpackage; class Foo {     // ... } var_dump(Foo::CLASS); //上面脚本输出 string(18) "vendorpackageFoo". 为什么要使用它 我们为什么要使用一个这样的常量,当然不是像上面那个例子一样只是获得类的全名.我们

  • 如何把php5.3版本升级到php5.4或者php5.5

    今天我们这篇php的技术文章主要为各位朋友们介绍如何使用yum进行安装php的5.4或者5.5版本.当然我们使用centos6.5作为我们的测试机器.其实非常简单,只要下面的两个命令就可以轻松的进行安装php的5.4版本了. 复制代码 代码如下: yum remove php php-bcmath php-cli php-common php-devel php-fpm  php-gd php-imap php-ldap php-mbstring php-mcrypt php-mysql  ph

  • PHP5.5在windows安装使用memcached服务端的方法

    PHP5.5 在windows下安装 memcached 的方法 下载服务端资源 http://download.csdn.net/detail/zsjangel/7104727 下载完成后,解压(我用的是 64位的,32位版本的我没有尝试过,应该没有问题),进入 DOS 命令行 先 cd 到解压后的目录 然后执行服务注册命令 memcached.exe -d install 卸载服务命令memcached.exe -d uninstall 然后启动服务memcached.exe -d star

  • PHP5.5和之前的版本empty函数的不同之处

    作为我最喜欢使用的函数之一,今天也终于发现这个函数的恶魔之处.洋洋洒洒写了以下代码,本地测试一切ok,到服务器上就SB了. 复制代码 代码如下: if(strlen($passwd) < 6 || empty($preg_replace("/\d/", "", $passwd))) {    //do something} 大致的意思就是,密码必须大于6位切不能只由数字组成.找遍服务器日志,发现如下错误: 复制代码 代码如下: PHP Fatal error:

  • php5.5新数组函数array_column使用

    PHP5.5发布了,其中增加了一个新的数组函数array_column,感觉不错的!但是低版本PHP要使用,得自己实现:参考地址:https://wiki.php.net/rfc/array_column 复制代码 代码如下: if(!function_exists('array_column')){     function array_column($input, $columnKey, $indexKey=null){         $columnKeyIsNumber      = (

  • PHP5.5迭代生成器用法实例详解

    本文实例讲述了PHP5.5迭代生成器用法.分享给大家供大家参考,具体如下: PHP5.5引入了迭代生成器的概念,迭代的概念早就在PHP有了,但是迭代生成器是PHP的一个新特性,这跟python3中的迭代生成器类似,看看PHP5.5的迭代生成器如何定义. <?php function xrange($start, $end, $step = 1) { for ($i = $start; $i <= $end; $i += $step) { yield $i; } } foreach (xrang

  • PHP迭代器的内部执行过程详解

    复制代码 代码如下: class myIterator implements Iterator {    private $position = 0;    private $array = array(        "first_element",        "second_element",        "last_element",    ); public function __construct() {        $this

随机推荐