The iteration submode provides a unified interface method for traversal clustering, so that the client can traverse Clustering Without knowing the internal structure of aggregation.
Structure of the iteration submode
:
General structure:
Roles involved:
Abstract iteration sub-(iterator) Role: defines the interface for Traversing aggregation.
The listiterator role implements the abstract iteration subinterface.
Abstract aggregation role: defines the common clustering methods and creates an iteration subobject for aggregation.
Arraylist role: This role can return an iteration subinstance that implements the iterator interface.
Client role: holds a reference to the clustering and iteration sub-instances, and aggregates the sub-instances through iteration.
Example:
Class diagram:
Abstract iteration sub-(iterator) role:
Package Oliver. designpattern. iterator; <br/>/** <br/> * <B> iterator interface. </B> <br/> * <p> <B> Description: </B> </P> <br/> * <! -- Add a detailed description here --> <br/> * none. <Br/> * <p> <B> modify the list: </B> </P> <br/> * <Table width = "100%" cellspacing = 1 cellpadding = 3 border = 1> <br/> * <tr bgcolor =" # ccccff "> <TD> NO. </TD> <TD> author </TD> <TD> modification date </TD> <TD> modification content </TD>/ tr> <br/> * <! -- Add the modification list here, for more information, see <br/> * <tr> <TD> 1 </TD> <TD> Oliver </TD> <TD> May 14,201 0 9:30:38 am </TD> <TD> creation type </TD> </tr> <br/> * </table> <br/> * @ version 1.0 <br /> * @ author Oliver <br/> * @ since 1.0 <br/> */<br/> Public interface iterator <br/> {<br/>/** <br/> * <B> move the pointer to the beginning of the aggregation. </B> <br/> * <p> <B> Description: </B> </P> <br/> * <! -- Add a detailed description here --> <br/> * none. <Br/> */<br/> void first (); <br/>/** <br/> * <B> obtain the element pointed to by the current pointer. </B> <br/> * <p> <B> Description: </B> </P> <br/> * <! -- Add a detailed description here --> <br/> * none. <Br/> * @ return <br/> */<br/> object next (); <br/>/** <br/> * <B> whether the next element exists. </B> <br/> * <p> <B> Description: </B> </P> <br/> * <! -- Add a detailed description here --> <br/> * none. <Br/> * @ return <br/> */<br/> Boolean hasnext (); <br/>}< br/>
The listiterator role is as follows:
Package Oliver. designpattern. iterator; <br/> public class listiterator implements iterator <br/> {<br/> private collection; </P> <p> private int Index = 0; </P> <p> private int size = 0; </P> <p> Public listiterator (Collection collection) <br/>{< br/> This. collection = collection; <br/> size = collection. size (); <br/>}< br/>/** <br/> * <B> obtains the elements pointed to by the current pointer in the aggregation. </B> <br/> * @ see Oliver. designpattern. iterator. iterator # Next () <br/> */<br/> Public object next () <br/> {<br/> return collection. getelement (index ++); <br/>}< br/>/** <br/> * <B> move the pointer to the beginning of the aggregation. </B> <br/> * @ see Oliver. designpattern. iterator. iterator # First () <br/> */<br/> Public void first () <br/> {<br/> Index = 0; <br/>}< br/>/** <br/> * <B> whether the next element exists. </B> <br/> * @ see Oliver. designpattern. iterator. iterator # hasnext () <br/> */<br/> Public Boolean hasnext () <br/>{< br/> return index <size; <br/>}< br/>
Abstract aggregate role:
Package Oliver. designpattern. iterator; <br/>/** <br/> * <B> abstract clustering class. </B> <br/> * <p> <B> Description: </B> </P> <br/> * <! -- Add a detailed description here --> <br/> * none. <Br/> * <p> <B> modify the list: </B> </P> <br/> * <Table width = "100%" cellspacing = 1 cellpadding = 3 border = 1> <br/> * <tr bgcolor =" # ccccff "> <TD> NO. </TD> <TD> author </TD> <TD> modification date </TD> <TD> modification content </TD>/ tr> <br/> * <! -- Add the modification list here, for more information, see <br/> * <tr> <TD> 1 </TD> <TD> Oliver </TD> <TD> May 14,201 0 9:27:47 am </TD> <TD> creation type </TD> </tr> <br/> * </table> <br/> * @ version 1.0 <br /> * @ author Oliver <br/> * @ since 1.0 <br/> */<br/> public abstract class collection <br/>{< br/> /** <br/> * <B> factory method :. </B> <br/> * <p> <B> Description: </B> </P> <br/> * <! -- Add a detailed description here --> <br/> * none. <Br/> * @ return an iterator <br/> */<br/> public abstract iterator (); </P> <p>/** <br/> * <B> obtains the clustering size. </B> <br/> * <p> <B> Description: </B> </P> <br/> * <! -- Add a detailed description here --> <br/> * none. <Br/> * @ return <br/> */<br/> public abstract int size (); </P> <p>/** <br/> * <B> obtain the collection element. </B> <br/> * <p> <B> Description: </B> </P> <br/> * <! -- Add a detailed description here --> <br/> * none. <Br/> * @ Param index <br/> * @ return <br/> */<br/> public abstract object getelement (INT index ); <br/>}< br/>
Arraylist role:
Package Oliver. designpattern. iterator; <br/> public class arraylist extends collection <br/>{< br/>/** <br/> * aggregates data. <Br/> */<br/> private object [] items = new object [10]; </P> <p>/** <br/> * Current pointer. <Br/> */<br/> private int currentindex = 0; </P> <p>/** <br/> * <B> Add an element to the aggregation. </B> <br/> * <p> <B> details: auto-increment of clustering size </B> </P> <br/> * <! -- Add a detailed description here --> <br/> * none. <Br/> * @ Param item <br/> */<br/> Public void add (Object item) <br/>{< br/> If (currentindex> = items. length) <br/>{< br/> object [] newitems = new object [items. length + 10]; <br/> system. arraycopy (items, 0, newitems, 0, items. length); <br/> items = newitems; <br/>}< br/> items [currentindex] = item; <br/> currentindex ++; <br/>}</P> <p>/** <br/> * <B> iterator. </B> <br/> * @ see Oliver. designpattern. iterator. collection # iterator () <br/> */<br/> @ override <br/> Public iterator () <br/>{</P> <p> return New listiterator (this ); <br/>}< br/>/** <br/> * <B> obtains the clustering size. </B> <br/> * <p> <B> Description: </B> </P> <br/> * <! -- Add a detailed description here --> <br/> * none. <Br/> * @ return <br/> */<br/> Public int size () <br/> {<br/> return items. length; <br/>}< br/> Public object getelement (INT index) <br/>{< br/> If (index <items. length) <br/> return items [Index]; <br/> else <br/> throw new indexoutofboundsexception (); <br/>}< br/>
Client role:
Package Oliver. designpattern. iterator; <br/> Import JUnit. framework. testcase; <br/> public class externaliteratortest extends testcase <br/> {<br/>/** <br/> * <B> intrinsic iteration subtest. </B> <br/> * <p> <B> Description: </B> </P> <br/> * <! -- Add a detailed description here --> <br/> * none. <Br/> */<br/> Public void testexternaliterator () <br/> {<br/> arraylist list = new arraylist (); <br/> for (INT I = 0; I <10; I ++) <br/> list. add (I); <br/> iterator it = List. iterator (); <br/> while (it. hasnext () <br/>{< br/> system. out. println (it. next (); <br/>}< br/>
Inner, inner?
Intrinsic child: Clustering itself does not provide a method to access its internal elements. Instead, it only traverses aggregation by aggregating the internal iterator. In this case, the iterator is an internal class and is part of the aggregation.
Extra child: Clustering itself provides a method to access its internal elements. It can be traversed through external iterations. In this case, the iterator is an external class and only maintains a reference to the aggregation.
Obviously, the above example is an extra iteration.
The arraylist class in Java uses an intrinsic subiteration.
In JDK, The arraylist class inherits the abstract class javasactlist. In javasactlist, there is an internal class itr:
Private class itr implements iterator <e >{< br/>/** <br/> * index of element to be returned by subsequent call to next. <br/> */<br/> int cursor = 0; <br/>/** <br/> * index of element returned by most recent call to next or <br/> * previous. reset to-1 if this element is deleted by a call <br/> * to remove. <br/> */<br/> int lastret =-1; <br/>/** <br/> * The modcount value that the iterator belie Ves that the backing <br/> * List shoshould have. if this expectation is violated, the iterator <br/> * has detected concurrent modification. <br/> */<br/> int expectedmodcount = modcount; <br/> Public Boolean hasnext () {<br/> return cursor! = Size (); <br/>}< br/> Public E next () {<br/> checkforcomodification (); <br/> try {<br/> E next = get (cursor); <br/> lastret = cursor ++; <br/> return next; <br/>} catch (indexoutofboundsexception e) {<br/> checkforcomodification (); <br/> throw new nosuchelementexception (); <br/>}< br/> Public void remove () {<br/> If (lastret =-1) <br/> throw new illegalstateexception (); <br/> checkforcomodif Ication (); <br/> try {<br/> using actlist. this. remove (lastret); <br/> If (lastret <cursor) <br/> cursor --; <br/> lastret =-1; <br/> expectedmodcount = modcount; <br/>} catch (indexoutofboundsexception e) {<br/> throw new concurrentmodificationexception (); <br/>}< br/> final void checkforcomodification () {<br/> If (modcount! = Expectedmodcount) <br/> throw new concurrentmodificationexception (); <br/>}< br/> private class listitr extends itr implements listiterator <e >{< br/> listitr (INT index) {<br/> cursor = index; <br/>}< br/> Public Boolean hasprevious () {<br/> return cursor! = 0; <br/>}< br/> Public e Previous () {<br/> checkforcomodification (); <br/> try {<br/> int I = cursor-1; <br/> E previous = get (I); <br/> lastret = cursor = I; <br/> return previous; <br/>} catch (indexoutofboundsexception e) {<br/> checkforcomodification (); <br/> throw new nosuchelementexception (); <br/>}< br/> Public int nextindex () {<br/> return cursor; <br/>}< br/> Public int previusindex () {<br/> return cursor-1; <br/>}< br/> Public void set (E) {<br/> If (lastret =-1) <br/> throw new illegalstateexception (); <br/> checkforcomodification (); <br/> try {<br/> using actlist. this. set (lastret, e); <br/> expectedmodcount = modcount; <br/>} catch (indexoutofboundsexception ex) {<br/> throw new concurrentmodificationexception (); <br/>}< br/> Public void add (E) {<br/> checkforcomodification (); <br/> try {<br/> using actlist. this. add (cursor ++, e); <br/> lastret =-1; <br/> expectedmodcount = modcount; <br/>} catch (indexoutofboundsexception ex) {<br/> throw new concurrentmodificationexception (); <br/>}< br/>}
Intrinsic vs intrinsic
An iterator has a very important attribute: the pointer of the current aggregation. With the current pointer, it can be iterated. If several clients iterate one aggregation at the same time, if the aggregation iterator is an exclusive sub, this is no problem. Several clients hold an independent pointer for each of the intrinsic sub. However, if the aggregation iterator is intrinsic, the problem arises: several clients simultaneously hold intrinsic subpointers and operate the pointers at the same time, the collection cannot be traversed normally.
An important reason for using the intrinsic iterator is that it can be shared and controlled by several different methods and objects. The advantage of using the intrinsic iterator is that it does not destroy the clustering encapsulation.
Java designers define the internal class itr as the iterator when designing javasactlist. That is to say, the designer does not want the client to change the iterator at will.
Project source code download: http://cid-2c8a0dc7c1eb1d71.skydrive.live.com/self.aspx/soft/Design%20Pattern/Iterator.7z