php教程:php设计模式介绍之迭代器模式(6)
排序迭代器
迭代器不仅可以显示全部或部分集合。而且,还可以按特定顺序显示集合。下面,创建一个按集合众介质的发布日期进行排序的迭代器。为了进行测试,请添加某些日期在 setUp() 方法中添加的项之后的介质实例。如果迭代器运行,则这些日期较后的项应该位于迭代操作的最前面。
class IteratorTestCase extends UnitTestCase {
// ...
function TestReleasedIteratorUsage() {
$this->lib->add(new Media(‘second’, 1999));
$this->lib->add(new Media(‘first’, 1989));
$this->assertIsA(
$it = $this->lib->getIterator(‘released’)
,’LibraryReleasedIterator’);
$output = array();
while ($item = $it->next()) {
$output[] = $item->name .’-’. $item->year;
}
$this->assertEqual(
‘first-1989 second-1999 name1-2000 name3-2001 name2-2002’
,implode(‘ ‘,$output));
}
}
该测试使用的项在每个迭代中略有不同:并不仅仅是在字符串值后添加 $name,而是,字符串同时具有 $name 和 $year 属性,这些属性随后将被添加到 $output 数组。LibraryReleasedIterator 的实现与 LibraryIterator 非常类似,除了 constuctor 中的一行语句:
class LibraryReleasedIterator extends LibraryIterator {
function __construct($collection) {
usort($collection, create_function(‘$a,$b’,’ return ($a->year - $b->year);’));
$this->collection = $collection;
}
}
用粗体表示的这一行将 $collection 数组排在迭代之前。你可以通过简单地继承 LibraryIterator 类,来避免复制该类的其它所有代码。可以使用外部迭代器来实现相同的排序迭代吗?是的,但是你必须注意完成它的诀窍。
class LibraryReleasedExternalIterator {
protected $collection;
protected $sorted_keys;
protected $key=-1;
function __construct($collection) {
$this->collection = $collection;
$sort_funct = create_function(
‘$a,$b,$c=false’,
‘static $collection;
if ($c) {
$collection = $c;
return;
}
return ($collection->get($a)->year -
$collection->get($b)->year);’);
$sort_funct(null,null,$this->collection);
$this->sorted_keys = $this->collection->keys();
usort($this->sorted_keys, $sort_funct);
}
function next() {
if (++$this->key >= $this->collection->count()) {
return false;
} else {
return $this->collection->get($this->sorted_keys[$this->key]);
}
}
}
其中,关键是创建用于排序的实用程序函数。排序函数必须能够访问集合,以便可以获取对照成员。然而,因为 gener- ated 函数在 usort() 中使用,没有将集合作为其它参数传递的选项。相反,你可以利用上述代码块中显示的诀窍,在利用 usort() 调用函数之前,将引用存储在函数中内部的集合中。排序的项是集合的关键字列表。当 usort() 完成时,关键字会按照集合中每个对象的 year 属性的顺序进行排序。在 next() 方法中,可以通过 get() 方法访问集合中的对象,而不是间接通过 $sorted_keys 映射。如果重新调用外部版本的 GoF 风格的迭代器,则不连续的数组或关键字中的字符串可能会有问题。可以使用针对 sim- ple 外部迭代器的相同诀窍,来减少关键字顺序不连贯的问题。