Iterator模式
理解Iterator(迭代子)模式
首先来看看概念:
Iterator模式可以顺序的访问一个聚集中的元素而不必暴露聚集的内部表象。
优点:
1 简化了聚集的节目。迭代子具备了遍历的接口,这样聚集的接口就不必具备遍历接口
2 每一个聚集对象都可以有一个或者跟多的迭代子对象,每一格迭代子的迭代状态可以使彼此独
立的(外禀迭代子)。
3 由于遍历算法被封装到迭代子对象中,因此迭代算法可以独立于聚集对象变化。客户端不必知
道聚集对象的类型,通过迭代子就可以读取和遍历聚集对象。这样的好处就是,聚集发生变化不
影响客户端的程序。
4 至于开销有待验证
在使用聚集的系统中,如果我们直接使用聚集会出现两类问题:
1 迭代逻辑不变,聚集变化,导致客户端要修改代码。
2 聚集不变,迭代方式需要变化,同样导致客户端要修改代码。
这实际上是违背了 开闭 原则。因为没有将不变的结构从系统中抽象出来,与可变的成分分割,
并将可变部分的这种实现封装起来。
Iterator模式将迭代逻辑封装到一个独立的Iterator对象中,从而与聚集本身分割开。Iterator
模式在客户端和聚集之间增加了一个中间层,从而使得客户端与聚集之间的通信由直接变成间接
。这样做的好处就是缓冲了客户端的变化对聚集的影响,以及聚集的变化对客户端的影响。
Iterator模式有两种实现方式;
1 白箱聚集与外禀迭代子:白箱聚集向外界提供访问自己内部元素的接口,从而使得外禀迭代子
可以通过聚集提供的方法实现迭代功能。
意义:一个常问的问题是客户端完全可以直接调用聚集提供的遍历方法来迭代,为何还要用迭代
模式? 回答是 客户端当然可以自行迭代,但是 迭代子对象和迭代子模式会将迭代过程抽象化
,将作为迭代消费者的客户端与迭代负责人迭代子责任分隔开,使得两者可以独立演化。在聚集
发生变化或者迭代方法发生改变的时候,迭代子作为一个中间层可以吸收变化的因素,而避免修
改客户端或聚集本身。
另外使用迭代子模式还可以对不同的聚集对象使用统一的迭代方法进行迭代。
2 黑箱聚集内禀迭代子:黑箱聚集不向外界提供遍历自己的元素的接口,因此聚集的成员只能被
聚集内部的方法访问。由于内禀迭代子恰好是聚集的成员,因此可以访问聚集元素。
下面代码示例:
白箱:
Aggregate:
abstract public class Aggregate
{
public Iterator createIterator()
{
return null;
}
}
Iterator:
public interface Iterator
{
void first();
void next();
boolean isDone();
Object currentItem();
}
ConcreteAggregate:
public class ConcreteAggregate extends Aggregate
{
private Object objs[]= {"Monk Tang",
"Monkey", "Pigsy",
"Sandy", "Horse"};
public Iterator createIterator()
{
return new ConcreteIterator(this);
}
public Object getElement(int index)
{
if (index < objs.length)
{
return objs[index];
}
else
{
return null;
}
}
public int size()
{
return objs.length;
}
}
ConcreteIterator:
public class ConcreteIterator implements Iterator
{
/**
* @directed
*/
private ConcreteAggregate agg;
private int index = 0;
private int size = 0;
public ConcreteIterator(ConcreteAggregate agg)
{
this.agg = agg;
size = agg.size();
index = 0 ;
}
public void first()
{
index = 0 ;
}
public void next()
{
if (index < size)
{
index++;
}
}
public boolean isDone()
{
return (index >= size);
}
public Object currentItem()
{
return agg.getElement(index);
}
}
Client:
public class Client
{
/**
* @directed
*/
private Iterator it;
/**
* @directed
*/
private Aggregate agg = new ConcreteAggregate();
public void operation()
{
it = agg.createIterator();
while( !it.isDone() )
{
System.out.println(it.currentItem().toString());
it.next();
}
}
public static void main(String[] args)
{
Client client = new Client();
client.operation();
}
}
下面是黑箱例子:
Iterator:
public interface Iterator
{
void first();
void next();
boolean isDone();
Object currentItem();
}
Aggregate:
abstract public class Aggregate
{
public Iterator createIterator()
{
return null;
}
}
ConcreteAggregate:
public class ConcreteAggregate extends Aggregate
{
private Object[] objs = {"Monk Tang",
"Monkey", "Pigsy",
"Sandy", "Horse"};
public Iterator createIterator()
{
return new ConcreteIterator();
}
private class ConcreteIterator
implements Iterator
{
private int currentIndex = 0;
public void first()
{
currentIndex = 0;
}
public void next()
{
if ( currentIndex < objs.length )
{
currentIndex++;
}
}
public boolean isDone()
{
return (currentIndex == objs.length);
}
public Object currentItem()
{
return objs[currentIndex];
}
}
}
Client:
public class Client
{
/**
* @directed
*/
private Iterator it;
/**
* @directed
*/
private Aggregate agg = new ConcreteAggregate();
public void operation()
{
it = agg.createIterator();
while( !it.isDone() )
{
System.out.println(it.currentItem().toString());
it.next();
}
}
public static void main(String[] args)
{
Client client = new Client();
client.operation();
}
}