Understanding Iterator Elements


The Iterator pattern is a solution that enables you to iterate over a collection's elements while maintaining good encapsulation and not having to expose the structure of the data. The Iterator pattern offloads the iteration responsibilities to a new object, and as a consequence, the collection class remains simple, and you can iterate over the collection more than once simultaneously.

The Iterator pattern consists of the following elements:

  • Iterator interface: The interface for iterating over the collection data

  • Concrete iterator: The implementation of the iterator interface

  • Collection interface: The interface that defines how to retrieve an iterator

  • Concrete collection: The implementation of the collection interface

The Iterator Interface

To define an iterator interface, you have to determine how much you want the iterator to be able to do. Initially it may seem important to define an interface that allows for moving forward or backward through the collection data. However, in practice, you generally don't need the ability to move both forward and backward through the collection data. Rather, you generally want to move through the data in only one direction, one element at a time. The ability to reset an iterator back to the start is also useful. The following interface accomplishes these goals, and it is the one that we use throughout this book.

package com.peachpit.aas3wdp.iterators {    public interface IIterator {       function reset():void;       function next():Object;       function hasNext():Boolean;    } }


The preceding interface allows you to iterate over a collection, one element at a time. The reset() method simply moves the cursor back to the start of the collection data. The next() method returns the next element and advances the cursor. The hasNext() method returns true if there is a next element and false if there is no next element. And the current() method returns the current element without advancing the cursor.

Note

It's important to understand that the IIterator interface is merely an interface. It does not dictate implementation. Although we might be accustomed to thinking of the word next as meaning moving forward, the next() method of an implementing class can just as easily move backward through a collection. For that matter an implementing class could skip every other element or even return random elements. The interface simply specifies what methods an implementing class must define.


The Concrete Iterator

The interface simply determines what methods the concrete iterator must implement. The concrete iterator defines the actual functionality. Perhaps one of the most common types of iterators for ActionScript is an iterator that can iterate over an array one element at a time starting with index 0. The following ArrayIterator definition accomplishes just that:

package com.peachpit.aas3wdp.iterators {    public class ArrayIterator implements IIterator {              private var _index:uint = 0;       private var _collection:Array;       public function ArrayIterator(collection:Array) {          _collection = collection;          _index = 0;       }       public function hasNext():Boolean {          return _index < _collection.length;       }       public function next():Object {          return _collection[_index++];       }       public function reset():void {          _index = 0;       }    } }


Of course, you can define many types of iterators depending on the collection data structures and the way in which you want to iterate over the data. The preceding example iterates over an array one element at a time with increasing indices. You could also define an iterator that returns the elements in reverse order, like this:

package com.peachpit.aas3wdp.iterators {    public class ArrayReverseIterator implements IIterator {       private var _index:uint = 0;       private var _collection:Array;       public function ArrayIterator(collection:Array) {          _collection = collection;          _index = _collection.length - 1;       }       public function hasNext():Boolean {          return _index >= 0;       }       public function next():Object {          return _collection[_index--];       }       public function reset():void {          _index = _collection.length - 1;       }    } }


Obviously, these are just two of the many types of iterators. Every iterator can define its own unique implementation. What is critical is that every iterator implements the same interface. The different implementations of the IIterator interface might allow access to different types of collections (associative arrays, for example). However, even if the collections are different, the iterator interface is the same, meaning you can access the data in the same way.

The Collection Interface

The collection interface defines the way in which you can access the iterator for a collection. The simplest interface is as follows:

package com.peachpit.aas3wdp.collections {    public interface ICollection {       unction iterator():IIterator;    } }


However, consider that you might want to enable many types of iterators for a collection. For example, you might want to allow a collection to return an iterator that advances one element at a time forward through the collection, or you might want to return an iterator that skips every other element in ascending order. For that reason, it is advantageous to define the interface as follows:

package com.peachpit.aas3wdp.collections {    public interface ICollection {       function iterator(type:String = null):IIterator;    } }


The implementing collection class can then return a different iterator type depending on the parameter passed to the method. The UIntCollection example in the next section illustrates this.

The Concrete Collection

The concrete collection class implements the collection interface. The following example rewrites the UIntCollection class so that it implements ICollection:

package com.peachpit.aas3wdp.collections {    import com.peachpit.aas3wdp.IIterator;    import com.peachpit.aas3wdp.ArrayIterator;    public class UIntCollection implements ICollection {       private var _data:Array;       public function UIntCollection() {          _data = new Array();       }       public function addElement(value:uint):void {          _data.push(value);       }       public function iterator(type:String = null):IIterator {          return new ArrayIterator(_data);       }    } }


The preceding implementation returns only one type of iterator. However, if appropriate, you could enable several types of iterators, and the iterator that is returned would depend on the parameter value, as in the following example:

public function iterator(type:String = null):IIterator {    if(type == "ArrayReverseIterator") {       return new ArrayReverseIterator(_data);    }    else {       new ArrayIterator(_data);    } }


In this example the user can create one UIntCollection object, and from the same interface she can request several different types of iterators.

var collection:UIntCollection = new UIntCollection(); collection.addElement(1); collection.addElement(20); collection.addElement(5); collection.addElement(15); var iteratorAscending:IIterator = collection.iterator(); var iteratorDescending:IIterator = collection.iterator("ArrayReverseIterator");





Advanced ActionScript 3 with Design Patterns
Advanced ActionScript 3 with Design Patterns
ISBN: 0321426568
EAN: 2147483647
Year: 2004
Pages: 132

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net