Iterator 迭代子模式提供了一种访问集合的公共机制。它能够让你以同样的方式遍历,访问和操作数据集合,如数组,文件夹,RSS集合,数据库数据集等等。

 

Php5 其中一个与 Php4 不同的地方就在于它封装了各种 iterator 接口,这使得在 Php5 中实现 iterator 迭代子变得非常容易。

 

在 Zend Framework 中也大量使用了 iterator 类接口。下面我将以 Zend_Feed 为例,看看它是如何实现 iterator 迭代子的 :

 

 

 

以下源代码经过简化,首先是 Zend_Feed_Element : 

 


/**

 * Zend_Feed_Element 用于封装 DOMElement

 */

class Zend_Feed_Element implements ArrayAccess

{

    // @var DOMElement DOM 对象

    protected $_element;

 

    // Zend_Feed_Element 构建函数.

    public function __construct($element = null)

    {

        $this->_element = $element;

    }


    // ......


    /**

     * ArrayAccess 接口函数

     * 判断元素属性是否存在

     */

    public function offsetExists($offset)

    {

        // ......

        return $this->_element->hasAttribute($offset);

    }

 

    /**

     * ArrayAccess 接口函数

     * 返回元素属性

     */

    public function offsetGet($offset)

    {

        // ......

        return $this->_element->getAttribute($offset);

    }


    /**

     * ArrayAccess 接口函数

     * 设置指定的元素属性值

     */

    public function offsetSet($offset, $value)

    {

        // ......

        return $this->_element->setAttribute($offset, $value);

    }


    /**

     * ArrayAccess 接口函数

     * 重置指定的元素属性值

     */

    public function offsetUnset($offset)

    {

        // ......

        return $this->_element->removeAttribute($offset);

    }


    // ......

}


 

注意,Zend_Feed_Element 实现了 ArrayAccess 接口,这意味着 Zend_Feed_Element 及其派生类都能以数组的形式被访问。

 

接下来是 Zend_Feed_Abstract 虚拟类 : 

 


require_once 'Zend/Feed/Element.php';


/**

 * Zend_Feed_Abstract 类是用于实现 feeds 的虚拟类

 * 它实现了两个 PHP5 的核心接口 : ArrayAccess 和 Iterator

 */

abstract class Zend_Feed_Abstract extends Zend_Feed_Element implements Iterator

{

    /**

     * 当前数据集合索引

     * 用于 iterator 实现

     * @var integer

     */

    protected $_entryIndex = 0;


    /**

     * 数据集

     * @var array

     */

    protected $_entries;


    // ......


    // Iterator 接口函数,重置索引位置

    public function rewind()

    {

        $this->_entryIndex = 0;

    }


    // Iterator 接口函数,返回当前记录

    public function current()

    {

        return new $this->_entryClassName(

            null,

            $this->_entries[$this->_entryIndex]);

    }


    // Iterator 接口函数,返回当前记录的索引

    public function key()

    {

        return $this->_entryIndex;

    }


    // Iterator 接口函数,索引位置下移

    public function next()

    {

        ++$this->_entryIndex;

    }


    // Iterator 接口函数,当前索引是否正确

    public function valid()

    {

        return 0 <= $this->_entryIndex && $this->_entryIndex < $this->count();

    }


    // ......

}


 

Zend_Feed_Abstract 实现了 ArrayAccess 以及 Iterator 接口,这使得我们可以像访问数组一样来访问所有继承自Zend_Feed_Abstract 的数据集。

 

最后是两个派生类 Zend_Feed_Rss 及 Zend_Feed_Atom 的实例 :

 

require_once 'Zend/Feed/Abstract.php';

class Zend_Feed_Rss extends Zend_Feed_Abstract
{
// ......
}

class Zend_Feed_Atom extends Zend_Feed_Abstract
{
// ......
}


 

事例代码 :

 

$channel = new Zend_Feed_Rss('http://rss.example.com/channelName');
foreach ($channel as $item) {
echo 'Title: ' . $item->title() . "n";
}

$feed = new Zend_Feed_Atom('http://atom.example.com/feed/');
foreach ($feed as $entry) {
echo 'Title: ' . $entry->title() . "n";
}


 

Iterator 为应用程序访问数据集合提供了统一的方法,它把操作数据集合的概念抽象出来,使得数据操作对于用户来说达到了真正的透明,同时使用户能够更专注于业务逻辑,在很大程度上提高了开发效率。