提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。C#和PHP自己已经实现了这个模式,例如C#里边的foreach方法。当我们要访问一个聚集而又不需要知道它内部结构的时候,可以考虑用迭代器模式,迭代器模式遍历是由它内部提供的方法实现的。
迭代器模式有四个角色:
迭代器:迭代器定义访问和遍历元素的接口
具体迭代器:具体迭代器实现迭代器接口,对该聚合遍历时跟踪当前位置
聚合:聚合定义创建相应迭代器对象的接口(可选)
具体聚合:具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例(可选)
意图:提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。
主要解决:不同的方式来遍历整个整合对象。
何时使用:遍历一个聚合对象。
如何解决:把在元素之间游走的责任交给迭代器,而不是聚合对象。
优点: 1、它支持以不同的方式遍历一个聚合对象。 2、迭代器简化了聚合类。 3、在同一个聚合上可以有多个遍历。 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
缺点:由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
使用场景: 1、访问一个聚合对象的内容而无须暴露它的内部表示。 2、需要为聚合对象提供多种遍历方式。 3、为遍历不同的聚合结构提供一个统一的接口。
注意事项:迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。
由于PHP自己有Iterator这个了,所以本次代码只做演示,只可意会,不要使用。先来一个不用聚合的:
<?php
//抽象迭代器 由于Iterator是关键字所有用MyIterator
abstract class MyIterator{
//第一个
abstract function First();
//下一个
abstract function Next();
//是否是最后一个
abstract function IsDone();
//当前对象
abstract function CurrentItem();
}
//具体的迭代器--不带聚集的
class ConcreteIterator extends MyIterator{
private $Aggregate;
private $Current = 0;
function __construct(Array $Aggregate)
{
$this->Aggregate = $Aggregate;
}
function First()
{
return $this->Aggregate[0];
}
function Next()
{
$this->Current++;
if($this->Current<count($this->Aggregate))
{
return $this->Aggregate[$this->Current];
}
else
{
return null;
}
}
function IsDone()
{
return $this->Current>=count($this->Aggregate)?true:false;
}
function CurrentItem()
{
return $this->Aggregate[$this->Current];
}
}
//调用
$Testarray = array('a','b','c');
$ConcreteIterator = new ConcreteIterator($Testarray);
while (!$ConcreteIterator->IsDone())
{
echo $ConcreteIterator->CurrentItem()." it's your turn.";
$ConcreteIterator->Next();
}
?>
上边这个,没有用到聚集,下边这段代码用到了聚集:
<?php
//抽象迭代器 由于Iterator是关键字所有用MyIterator
abstract class MyIterator{
//第一个
abstract function First();
//下一个
abstract function Next();
//是否是最后一个
abstract function IsDone();
//当前对象
abstract function CurrentItem();
}
//抽象聚合
abstract class Aggregate {
abstract function CreateIterator();
}
//具体的迭代器
class ConcreteIterator extends MyIterator{
private $Aggregate;
private $Current = 0;
function __construct(ConcreteAggregate $Aggregate)
{
$this->Aggregate = $Aggregate;
}
function First()
{
return $this->Aggregate->Aggregates[0];
}
function Next()
{
$this->Current++;
if($this->Current<$this->Aggregate->Count())
{
return $this->Aggregate->Aggregates[$this->Current];
}
else
{
return null;
}
}
function IsDone()
{
return $this->Current>=$this->Aggregate->Count()?true:false;
}
function CurrentItem()
{
return $this->Aggregate->Aggregates[$this->Current];
}
}
//具体的聚合
class ConcreteAggregate extends Aggregate{
public $Aggregates = array();
public function CreateIterator()
{
return new ConcreteIterator($this);
}
//返回聚集总个数
public function Count()
{
return count($this->Aggregates);
}
}
//测试类
class Test{
public $Name;
function __construct($Name)
{
$this->Name = $Name;
}
public function GetName()
{
echo $this->Name;
}
}
//调用
$TestA = new Test("DaLi");
$TestB = new Test("ErGou");
$ConcreteAggregate = new ConcreteAggregate();
$ConcreteAggregate->Aggregates = array($TestA,$TestB);
$ConcreteIterator = $ConcreteAggregate->CreateIterator();
while (!$ConcreteIterator->IsDone())
{
echo $ConcreteIterator->CurrentItem()->GetName()." it's your turn.";
$ConcreteIterator->Next();
}
?>