🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
>[info]迭代器模式 (Iterator),又叫做游标(Cursor)模式。提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。就像一个双色球彩票开奖一 样,每次都是摇出七个球,不能能摇不是七个球的中奖号码组合。概括为提供一种方法访问一个容器(Container)对象中各个元素,而又不需暴露该对象的内部细节。 **优点:** 1. 访问一个聚合对象的内容而无须暴露它的内部表示。 2. 遍历任务交由迭代器完成,这简化了聚合类。 3. 它支持以不同方式遍历一个聚合,甚至可以自定义迭代器的子类以支持新的遍历。 4. 增加新的聚合类和迭代器类都很方便,无须修改原有代码。 5. 封装性良好,为遍历不同的聚合结构提供一个统一的接口。 **缺点:** * 每次遍历都是整个集合,不能单独取出元素。增加了类的个数,这在一定程度上增加了系统的复杂性。 **应用场景:** 需要操作集合里的全部元素 当你需要访问一个聚合对象,而且不管这些对象是什么都需要遍历的时候,就应该考虑使用迭代器模式。另外,当需要对聚集有多种方式遍历时,可以考虑去使用迭代器模式。迭代器模式为遍历不同的聚集结构提供如开始、下一个、是否结束、当前哪一项等统一的接口 **实际应用:** 如[Java](http://c.biancheng.net/java/)语言中的 Collection、List、Set、Map 等都包含了迭代器 ## **模式的结构** 1. 抽象聚合(Aggregate)角色:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。 2. 具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。 3. 抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、first()、next() 等方法。 4. 具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。 ![](https://img.kancloud.cn/fb/52/fb52c04e872fce60d6979f9da28a75eb_521x376.png) ``` //抽象聚合 interface Aggregate { public function add($obj); public function remove(); /** * * @return Iterator [description] */ public function getIterator(); } //具体聚合 class ConcreteAggregate implements Aggregate { private $list=array(); public function add($obj) { //尾部插入一个或多个新单元(入栈) array_push($this->list, $obj); } public function remove() { array_pop($this->list); } /** * * @return Iterator [description] */ public function getIterator() { return(new ConcreteIterator($this->list)); } } //抽象迭代器(多个I因为php系统已有Iterator类) interface IIterator { function first(); function next(); function hasNext(); } //具体迭代器 class ConcreteIterator implements IIterator { private $list=array(); private $index=-1; public function __construct(array $list) { $this->list=$list; } /** * * @return boolean [description] */ public function hasNext() { if($this->index < count($this->list)-1) { return true; }else{ return false; } } public function first() { $this->index=0; $obj=$this->list[$this->index]; return $obj; } public function next() { $obj=null; if($this->hasNext()) { $obj=$this->list[++$this->index]; //$this->index += 1 //$obj=$this->list[$this->index] } return $obj; } } class Client { public static function main() { $Aggregate=new ConcreteAggregate(); $Aggregate->add("中山大学"); $Aggregate->add("华南理工"); $Aggregate->add("韶关学院"); print_r("聚合的内容有:<br>"); //获取迭代器 $Iterator=$Aggregate->getIterator(); //遍历迭代器 while($Iterator->hasNext()) { $ob=$Iterator->next(); print_r("--".$ob."--<br>"); } $ob=$Iterator->first(); print_r("First:".$ob); } } Client::main(); 输出: 聚合的内容有: --中山大学-- --华南理工-- --韶关学院-- First:中山大学 ``` php标准库(SPL)中提供了迭代器接口 Iterator,要实现迭代器模式,实现该接口即可。 ~~~ class sample implements Iterator { private $_items ; public function __construct(&$data) { $this->_items = $data; } public function current() { return current($this->_items); } public function next() { next($this->_items); } public function key() { return key($this->_items); } public function rewind() { reset($this->_items); } public function valid() { return ($this->current() !== FALSE); } } // client $data = array(1, 2, 3, 4, 5); $sa = new sample($data); foreach ($sa AS $key => $row) { echo $key, ' ', $row, '<br />'; } /* 输出: 0 1 1 2 2 3 3 4 4 5 */ ~~~ Yii FrameWork Demo ``` class CMapIterator implements Iterator { /** * @var array the data to be iterated through */ private $_d; /** * @var array list of keys in the map */ private $_keys; /** * @var mixed current key */ private $_key; /** * Constructor. * @param array the data to be iterated through */ public function __construct(&$data) { $this->_d=&$data; $this->_keys=array_keys($data); } /** * Rewinds internal array pointer. * This method is required by the interface Iterator. */ public function rewind() { $this->_key=reset($this->_keys); } /** * Returns the key of the current array element. * This method is required by the interface Iterator. * @return mixed the key of the current array element */ public function key() { return $this->_key; } /** * Returns the current array element. * This method is required by the interface Iterator. * @return mixed the current array element */ public function current() { return $this->_d[$this->_key]; } /** * Moves the internal pointer to the next array element. * This method is required by the interface Iterator. */ public function next() { $this->_key=next($this->_keys); } /** * Returns whether there is an element at current position. * This method is required by the interface Iterator. * @return boolean */ public function valid() { return $this->_key!==false; } } $data = array('s1' => 11, 's2' => 22, 's3' => 33); $it = new CMapIterator($data); foreach ($it as $row) { echo $row, '<br />'; } /* 输出: 11 22 33 */ ```