Iterator Pattern - CoffeeScript Design Patterns

By on

While there is a lot of complexity in setting up an Iterator, I really like the consistency its interface adds to an application. The GoF implementation uses the List class, so I’ve used it here as well. One could totally do without it though. The same goes for the abstract Iterator and Aggregate classes. I like them though because it makes things easier to remember when you’re creating a new iterator. Simply include the classes and extend them.

[code lang=“coffee”]

Defines an interface for accessing/traversing elements.

class Iterator
first: () ->
next: () ->
isDone: () ->
currentItem: () ->

  1. * Implements the Iterator interface
  2. * Keeps track of the current position in the traversal
  3. of the aggregate

class ConcreteIterator extends Iterator
constructor: (@list) ->
@current = 0
first: () ->
@current = 0
next: () ->
@current += 1
isDone: () ->
@current >= @list.count()
currentItem: () ->
throw new Error "IteratorOutOfBounds" if @isDone()
@list.get @current

  1. Defines an interface for creating an Iterator object

class Aggregate
createIterator: () ->

  1. Implements the Iterator creation interface to return an
  2. instance of the proper ConcreteIterator

class ConcreteAggregate extends Aggregate
createIterator: (items) ->
list = new List()
for key, val of items
val.POINTER = key
list.append val
new ConcreteIterator list
[/code]

Usage:

This example assumes we have an indexed set of objects called items.

[code lang=“coffee”]
aggregate = new ConcreteAggregate()
iterator = aggregate.createIterator items

while not iterator.isDone()
current = iterator.currentItem()

Do something with the item hereā€¦

iterator.next()
[/code]