php教程:php设计模式介绍之迭代器模式(7)

http://www.itjxue.com  2015-07-17 08:20  来源:未知  点击次数: 

SPL 迭代器

《迭代器设计模式和 PHP》中必须论述“标准 PHP 库”(SPL)迭代器。虽然,使用 while 循环结构可以非常紧凑,并且也很有用,但是 PHP 代码或许更适合数组迭代的 foreach 结构。直接在 foreach 循环中使用集合合适吗?这其实就是 SPL 迭代器的目标。(尽管本章整篇都是写 PHP5,下列 SPL 代码只能在 PHP5 中运行,并且仅当在 PHP5 编译中将 SPL 启用。)

Fuecks 写过一篇文章,详细地介绍了 SPL 和 SPL 迭代器;请参阅。使用 SPL 是一种完全不同的实现迭代的方法,因此首先介绍一个新单元测试例子和一个新的类 ForeachableLibrary。

class  SplIteratorTestCase  extends  UnitTestCase  {
protected  $lib;
function  setup()  {
$this->lib  =  new  ForeachableLibrary;
$this->lib->add(new  Media(‘name1’,  2000));
$this->lib->add(new  Media(‘name2’,  2002));
$this->lib->add(new  Media(‘name3’,  2001));
}
function  TestForeach()  {
$output  = ‘’;
foreach($this->lib  as  $item)  {
$output  .=  $item->name;
}
$this->assertEqual(‘name1name2name3’,  $output);
}
}

ForeachableLibrary 是实现 SPL 迭代器接口的集合。你必须执行 5 个函数来创建 SPL 迭代器:current()、next()、key()、valid() 和 rewind()。 key() 返回集合的当前索引。 rewind() 类似于 reset():在集合启动时重新启动迭代。

class  ForeachableLibrary
extends  Library implements  Iterator  {
protected  $valid;
function  current()  {
return  current($this->collection);
}
function  next()  {
$this->valid  =  (false  !==  next($this->collection));
}
function  key()  {
return  key($this->collection);
}
function  valid()  {
return  $this->valid;
}
function  rewind()  {
$this->valid  =  (false  !==  reset($this->collection));
}
}

这里,该代码仅仅实现了处理 $collection 属性的必需的函数。(如果你没有实现所有 5 个函数,并且将实现迭代器添加到类 definition,则 PHP 将出现致命错误。)测试尚不成熟,因此,什么都有可能发生。存在一个问题:事实受限于一种迭代类型 - 排序,或者 fil- tering 不可用。可以采取措施来调整这种情况?是的!应用从策略模式中学到的知识(请参阅第 7 章),将 SPL 迭代器的 5 个函数作为另一个对象的示例。这是关于 PolymorphicForeachableLibrary 的测试。

class  PolySplIteratorTestCase  extends  UnitTestCase  {
protected  $lib;
function  setup()  {
$this->lib  =  new  PolymorphicForeachableLibrary;
$this->lib->add(new  Media(‘name1’,  2000));
$this->lib->add(new  Media(‘name2’,  2002));
$this->lib->add(new  Media(‘name3’,  2001));
}
function  TestForeach()  {
$output  = ‘’;
foreach($this->lib  as  $item)  {
$output  .=  $item->name;
}
$this->assertEqual(‘name1name2name3’,  $output);
}
}

这种情况与 SplIteratorTestCase 测试的唯一差别在于 $this->lib 属性类是在 setUp() 方法中创建的。这意味着:这两个类的运行方式必须一致。PolymorphicForeachableLibrary:class  PolymorphicForeachableLibrary扩展库

implements  Iterator  {
protected  $iterator;
function  current()  {
return  $this->iterator->current();
}
function  next()  {
return  $this->iterator->next();
}
function  key()  {
return  $this->iterator->key();
}
function  valid()  {
return  $this->iterator->valid();
}
function  rewind()  {
$this->iterator  =
new  StandardLibraryIterator($this->collection);
$this->iterator->rewind();
}
}

扩展库加入集合处理方法。并添加 SPL 方法,这些方法代表了 $iterator 属性,在 rewind() 中创建。以下是StandardLibraryIterator 的代码。

class  StandardLibraryIterator  {
protected  $valid;
protected  $collection;
function  __construct($collection)  {
$this->collection  =  $collection;
}
function  current()  {
return  current($this->collection);
}
function  next()  {
$this->valid  =  (false  !==  next($this->collection));
}
function  key()  {
return  key($this->collection);
}
function  valid()  {
return  $this->valid;
}
function  rewind()  {
$this->valid  =  (false  !==  reset($this->collection));
}
}

该代码看起来很熟悉:实际上,这来自于 5 个 SPL 函数ForeachableLibrary 类。

(责任编辑:IT教学网)

更多