迭代器(Iterator)模式,又叫做游标(Cursor)模式。GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。
百度百科: http://baike.baidu.com/view/9791023.htm?fr=aladdin
解释
上面这名话可能多数人看得似懂非懂,什么叫做访问容器的各个元素,又不暴露对象的内部细节呢?尤其是网上很多例子都过于简单,直接扔一个数组,然后去实现了迭代器的各种方法,如下:
<?php
class SomeCollection implements Iterator
{
protected $_data;
protected $_pos;
function __construct($data)
{
$this->_data = $data;
$this->_pos = 0;
}
function current()
{
$row = $this->_data[$this->_pos];
return $row;
}
function next()
{
$this->_pos++;
}
function valid()
{
return $this->_pos >= 0 && $this->_pos <count($this->_data);
}
function key()
{
return $this->_pos;
}
function rewind()
{
$this->_pos = 0;
}
}
$array = array(
array('url' => 'www.zeroplace.cn'),
array('url' => 'www.baidu.com'),
array('url' => 'www.sina.com.cn'),
array('url' => 'www.google.com'),
array('url' => 'www.qq.com'),
);
$coll = new SomeCollection($array);
foreach ($coll as $row) {
echo $row['url'], " ";
}
这样的例子就不能够说明迭代器的作用,因为它不能说明迭代器隐藏了内部的数据结构,传进去的和返回出来的完全是一样的数据。
迭代器怎么用
我只能说在不同的场合有不同的用法。比如我把上面的例子修改一下,可能就可以说明迭代器可以隐藏数据结构这个特性了。请看如下代码。
<?php
class SomeCollection implements Iterator
{
protected $_data;
protected $_pos;
function __construct($data)
{
$this->_data = $data;
$this->_pos = 0;
}
function current()
{
$row = $this->_data[$this->_pos];
$row['ip'] = gethostbyname($row['url']);
return $row;
}
function next()
{
$this->_pos++;
}
function valid()
{
return $this->_pos >= 0 && $this->_pos <count($this->_data);
}
function key()
{
return $this->_pos;
}
function rewind()
{
$this->_pos = 0;
}
}
$array = array(
array('url' => 'www.zeroplace.cn'),
array('url' => 'www.baidu.com'),
array('url' => 'www.sina.com.cn'),
array('url' => 'www.google.com'),
array('url' => 'www.qq.com'),
);
$coll = new SomeCollection($array);
foreach ($coll as $row) {
echo $row['url'], ' ', $row['ip'], " ";
}
这样我觉得就可以说明迭代器能隐藏数据结构这个特性了。我们的数据传进去的时候每行数据只有一个url属性,但是迭代出来的时候多了一个ip属性。这样对外部的使用者来说就是有两个属性(url和ip), 它不需要知道这个ip字段是创建者传入的还是在迭代器中产生的。
更一般的做法
这里current方法返回的是一个关联数组,更常规的做法是返回一个对象,此时这个迭代器可能还需要一个对象创建器。