http://www.cnblogs.com/singlepine/archive/2005/10/30/265024.html
设计模式-iterator(q代?
一?引言
q代q个名词对于熟悉Java的h来说l对不陌生。我们常怋用JDK提供的P代接口进行java collection的遍历:
Iterator it = list.iterator();

while(it.hasNext())
{
//using “it.next();”do some businesss logic
}
而这是关于q代器模式应用很好的例子?br />
二?定义与结?/strong>
q代器(IteratorQ模式,又叫做游标(CursorQ模式。GOFl出的定义ؓQ提供一U方法访问一个容器(containerQ对象中各个元素Q而又不需暴露该对象的内部l节?br />
从定义可见,q代器模式是为容器而生。很明显Q对容器对象的访问必然涉及到遍历法。你可以一股脑的将遍历Ҏ塞到容器对象中去Q或者根本不L供什么遍历算法,让用容器的己去实现d。这两种情况好像都能够解决问题?br />
然而在前一U情况,容器承受了过多的功能Q它不仅要负责自?#8220;容器”内的元素l护Q添加、删除等{)Q而且q要提供遍历自n的接口;而且׃遍历状态保存的问题Q不能对同一个容器对象同时进行多个遍历。第二种方式倒是省事Q却又将容器的内部细节暴露无遗?br />
而P代器模式的出玎ͼ很好的解决了上面两种情况的弊端。先来看下P代器模式的真面目吧?
q代器模式由以下角色l成Q?br />
1) q代器角ԌIteratorQ:q代器角色负责定义访问和遍历元素的接口?br />
2) 具体q代器角ԌConcrete IteratorQ:具体q代器角色要实现q代器接口,q要记录遍历中的当前位置?br />
3) 容器角色QContainerQ:容器角色负责提供创徏具体q代器角色的接口?br />
4) 具体容器角色QConcrete ContainerQ:具体容器角色实现创徏具体q代器角色的接口——这个具体P代器角色于该容器的结构相兟?br />
q代器模式的cd如下Q?br />
从结构上可以看出QP代器模式在客户与容器之间加入了P代器角色。P代器角色的加入,可以很好的避免容器内部l节的暴Ԍ而且也得设计符?#8220;单一职责原则”?br />
注意Q在q代器模式中Q具体P代器角色和具体容器角色是耦合在一L——遍历算法是与容器的内部l节紧密相关的。ؓ了客户E序从与具体q代器角色耦合的困境中q出来Q避免具体P代器角色的更换给客户E序带来的修改,q代器模式抽象了具体q代器角Ԍ使得客户E序更具一般性和重用性。这被称为多态P代?br />
三?举例
׃q代器模式本w的规定比较松散Q所以具体实C׃花八门。我们在此仅举一例,Ҏ不能实现方式一一呈现。因此在举例前,我们先来列D下P代器模式的实现方式?
1QP代器角色定义了遍历的接口Q但是没有规定由谁来控制q代。在Java collection的应用中Q是由客L序来控制遍历的进E,被称为外部P代器Q还有一U实现方式便是由q代器自w来控制q代Q被UCؓ内部q代器。外部P代器要比内部q代器灵zR强大,而且内部q代器在java语言环境中,可用性很弱?br />
2Q在q代器模式中没有规定谁来实现遍历法。好像理所当然的要在P代器角色中实现。因为既便于一个容器上使用不同的遍历算法,也便于将一U遍历算法应用于不同的容器。但是这样就破坏掉了容器的封装——容器角色就要公开自己的私有属性,在java中便意味着向其他类公开了自qU有属性?br />
那我们把它放到容器角色里来实现好了。这栯P代器角色p架空Z仅存放一个遍历当前位|的功能。但是遍历算法便和特定的容器紧紧l在一起了?br />
而在Java Collection的应用中Q提供的具体q代器角色是定义在容器角色中的内部类。这样便保护了容器的装。但是同时容器也提供了遍历算法接口,你可以扩展自qq代器?br />
好了Q我们来看下Java Collection中的q代器是怎么实现的吧?br />
//q代器角Ԍ仅仅定义了遍历接?/span>


public interface Iterator
{
boolean hasNext();
Object next();
void remove();
}

//容器角色Q这里以ListZ。它也仅仅是一个接口,׃|列出来?br />
//具体容器角色Q便是实CList接口的ArrayList{类。ؓ了突出重点这里指|列和P代器相关的内?br />
//具体q代器角Ԍ它是以内部类的Ş式出来的。AbstractList是ؓ了将各个具体容器角色的公共部分提取出来而存在的?/span>


public abstract class AbstractList extends AbstractCollection implements List
{
……
//q个便是负责创徏具体q代器角色的工厂Ҏ

public Iterator iterator()
{
return new Itr();
}

//作ؓ内部cȝ具体q代器角?/span>


private class Itr implements Iterator
{
int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;


public boolean hasNext()
{
return cursor != size();
}


public Object next()
{
checkForComodification();

try
{
Object next = get(cursor);
lastRet = cursor++;
return next;

} catch(IndexOutOfBoundsException e)
{
checkForComodification();
throw new NoSuchElementException();
}
}


public void remove()
{
if (lastRet == -1)
throw new IllegalStateException();
checkForComodification();


try
{
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;

} catch(IndexOutOfBoundsException e)
{
throw new ConcurrentModificationException();
}
}


final void checkForComodification()
{
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
至于q代器模式的使用。正如引a中所列那P客户E序要先得到具体容器角色Q然后再通过具体容器角色得到具体q代器角艌Ӏ这样便可以使用具体q代器角色来遍历容器?#8230;…
四?实现自己的P代器
在实现自qq代器的时候,一般要操作的容器有支持的接口才可以。而且我们q要注意以下问题Q?
在P代器遍历的过E中Q通过该P代器q行容器元素的增减操作是否安全呢Q?br />
在容器中存在复合对象的情况,q代器怎样才能支持深层遍历和多U遍历呢Q?br />
以上两个问题对于不同l构的容器角Ԍ各不相同Q值得考虑?br />
五?适用情况
׃面的讲述Q我们可以看P代器模式l容器的应用带来以下好处Q?br />
1) 支持以不同的方式遍历一个容器角艌Ӏ根据实现方式的不同Q效果上会有差别?br />
2) 化了容器的接口。但是在java Collection中ؓ了提高可扩展性,容器q是提供了遍历的接口?br />
3) 对同一个容器对象,可以同时q行多个遍历。因为遍历状态是保存在每一个P代器对象中的?br />
由此也能得出q代器模式的适用范围Q?br />
1) 讉K一个容器对象的内容而无需暴露它的内部表示?br />
2) 支持对容器对象的多种遍历?br />
3) 为遍历不同的容器l构提供一个统一的接口(多态P代)?br />
六?ȝ
q代器模式在我们的应用中很广泛,希望本文能帮助你理解它。如有不对之处,q请不吝指正?

]]>