概述
迭代器(Iterator)模式,又叫做游标(Cursor)模式。GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。
案例
黑枣电视公司的在生产的电视机,使用遥控器[后一个]和[前一个]按钮调节频道。当按下[后一个]按钮时,将切换到下一个预置的频道。想象一下在陌生的城市中的旅店中看电视。当改变频道时,重要的不是几频道,而是节目内容。如果对一个频道的节目不感兴趣,那么可以换下一个频道,而不需要知道它是几频道。。
分析OOA:
迭代器模式是为容器而生。很明显,对容器对象的访问必然涉及到遍历算法。这里有两个方案:
方案一、可以将遍历方法塞到容器对象中去
方案二、容器不去提供什么遍历算法,让使用容器的人自己去实现去吧。
方案一中,容器承受了过多的功能,它不仅要负责自己“容器”内的元素维护(添加、删除等等),而且还要提供遍历自身的接口;而且由于遍历状态保存的问题,不能对同一个容器对象同时进行多个遍历。方案二倒是省事又提高了容器的内聚能力。
设计OOD:
<UML>
<说明>
编程 OOP:
<代码>
//迭代器角色(Iterator) interface ChannelIterator { /** * 判断可否向下移动游标 * @abstract * @return boolean */ public function moveNext(); /** * 将游标置0 * @abstract * @return none */ public function first(); /** * 向前移动游标 * @abstract * @return none */ public function next(); /** * 取得当前游标所指数据项 * @abstract * @return none */ public function current(); } //具体迭代器角色(Concrete Iterator) class TvChannelIterator implements ChannelIterator { private $list = null; private $index = 0; public function __construct($list){ $this->list = $list; $index = 0; } public function moveNext() { if($this->index < count($this->list)){ return true; }else{ return false; } } public function first() { $this->index = 0; } public function next() { if( $this->index < count($this->list)) $this->index++; } public function current() { return $this->list[$this->index]; } } //容器角色(Container) interface ChannelList { /** * 取得一个具体迭代器角色实例 * @abstract * @return mixed 具体迭代器角色实例 */ public function getIterator(); } //具体容器角色(Concrete Container) class TvChannellist implements ChannelList { private $list; public function __construct() { $this->list = array( '0' => '北京台', '1' => '山东台', '2' => '湖南台', '3' => '凤凰台', '4' => '河北台' ); } public function getIterator() { return new TvChannelIterator($this->list); } public function getLength() { return count($this->list); } public function getChannel($index = 0) { return $this->list[$index]; } }
测试用例Test Case:
<代码>
class testDriver { public function run() { $channels = new TvChannellist(); $iterator = $channels->getIterator(); while($iterator->moveNext()){ echo "频道:". $iterator->current()."\n"; $iterator->next(); } } } $test = new testDriver(); $test->run();
<输出>
小结:
面向对象设计原则中有一条是类的单一职责原则,所以我们要尽可能的去分解这些职责,用不同的类去承担不同的职责。Iterator模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明的访问集合内部的数据。
【常用情境】:
1.访问一个聚合对象的内容而无需暴露它的内部表示。
2.支持对聚合对象的多种遍历。
3.为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)。
【优点】
支持以不同的方式遍历一个容器角色。根据实现方式的不同,效果上会有差别。
2. 简化了容器的接口。
3. 对同一个容器对象,可以同时进行多个遍历。因为遍历状态是保存在每一个迭代器对象中的。
【缺点 】
由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
将容器的内部细节向迭代器暴露无遗
*********************转载请注明来源********************
* 作者:叶文涛
* 标题:Php设计模式之迭代器模式Iterator Pattern(一)
* 参考:
*《Head First设计模式》Eric Freeman等著
*《PHP设计模式》Aaron Saray等著,梁志敏等译(PS:翻译的是狗屁水平)
* Java设计模式之迭代器模式 http://www.51cto.com/specbook/11/9578.htm
* .NET设计模式(18):迭代器模式(Iterator Pattern)http://www.cnblogs.com/Terrylee/archive/2006/09/16/Iterator_Pattern.html
*********************转载请注明来源********************