首页 > 编程 > PHP > 正文

PHP设计模式漫谈之迭代器模式

2020-03-22 17:59:23
字体:
来源:转载
供稿:网友
  • 原文出处:blogspot

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

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

    图1 迭代器模式

    参与者:

    客户端(Client):引用迭代器模式的方法在一组值或对象上执行一个循环。

    ◆迭代器(Iterator):在迭代过程上的抽象,包括next(),isFinished(),html' target='_blank'>current()等方法。

    ◆具体迭代器(ConcreteIterators):在一个特定的对象集,如数组,树,组合,集合等上实现迭代。

    通过Traversable接口,PHP原生态支持迭代器模式,这个接口由Iterator和IteratorAggregate做了扩展,这两个子接口不仅是定义了一套标准的方法,每个Traversable对象都可以原封不动地传递给foreach(),foreach是迭代器的主穴ky"http://www.it165.net/qq/" target="_blank" class="keylink">qq/zbuntsujrEl0ZXJhdG9yyrXP1srH1ebV/bXEtfy0+sb3o6y2+El0ZXJhdG9yQWdncmVnYXRlysfT0Mbky/zWsNTwtcRUcmF2ZXJzYWJsZbbUz/OjrMv8zai5/WdldEl0ZXJhdG9yKCm3vbeot7W72NK7uPZJdGVyYXRvcqGjPC9wPgo8aW1nIHNyYz0="http://www.it165.net/uploadfile/files/2015/0722/20150722191927643.png" alt="">

     

    标准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++;  } }  $arrayarray = array('A', 'B', 'C', 'D'); echo "Collection: "; foreach (new Collection($array) as $key => $value) {  echo "$key => $value. "; } echo "";

    /**  * 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 "";

    // 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 ""; // 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 "";


    PHP编程

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表