WebjxCom提示:php教程:php设计模式介绍之迭代器模式.
不同的迭代器API
虽然前面的代码是GoF所述迭代器模式的完整实现
,你还可能会发现四种方法的API有一点臃肿
。如果是
,你可以将collapsenext(),currentItem(),和isDone()都并入next()中,用来从集合中返回本项或下一项,或者如果整个集合被遍历过了,则返回false
。这是一个测试不同API的代码:
classIteratorTestCaseextendsUnitTestCase{
//...
functionTestMediaIteratorUsage(){
$this->assertIsA(
$it=$this->lib->getIterator(‘media’)
,’LibraryIterator’);
$output=‘’;
while($item=$it->next()){
$output.=$item->name;
}
$this->assertEqual(‘name1name2name3’,$output);
}
}
在上述代码中,注意简化的循环控制结构。next()返回对象或者false,允许你在while循环条件中执行分配。下面的一些示例检验使用较小接口的不同迭代器模式。为了方便,将Library::getIterator()方法更改为参数化的Factory,以便你可以从单一方法中获取四种的方法迭代器或两种方法的迭代器(next()和reset())。
classLibrary{
//...
functiongetIterator($type=false){
switch(strtolower($type)){
case‘media’:
$iterator_class=‘LibraryIterator’;
break;
default:
$iterator_class=‘LibraryGofIterator’;
}
returnnew$iterator_class($this->collection);
}
}
这里面的Library::getIterator()现在接受一个参数以选择返回什么样的迭代器。缺省为LibraryGofIterator(因此现有的测试仍然能够通过)。将字符串媒体传递给所创建的方法,并返回LibraryIterator。这是一些实现LibraryIterator的代码:
classLibraryIterator{
protected$collection;
function__construct($collection){
$this->collection=$collection;
}
functionnext(){
returnnext($this->collection);
}
}
请注意调试结果的红色标记!什么导致发生错误“Equalexpectationfailsatcharacter4withname1name2name3andname2name3”?不知何故,跳过了第一次迭代-这是bug。要修订该错误,对于next()方法的第一次调用,返回current()。
classLibraryIterator{
protected$collection;
protected$first=true;
function__construct($collection){
$this->collection=$collection;
}
functionnext(){
if($this->first){
$this->first=false;
returncurrent($this->collection);
}
returnnext($this->collection);
}
}
Presto!绿色条和改进的while循环迭代器。