The Iterator design pattern provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
A visualization of the classes and objects participating in this pattern.
The classes and objects participating in this pattern include:
AbstractIterator
)
Iterator
)
AbstractCollection
)
Collection
)
This structural code demonstrates the Iterator pattern which provides for a way to traverse (iterate) over a collection of items without detailing the underlying structure of the collection.
using System;
using System.Collections.Generic;
namespace Iterator.Structural
{
/// <summary>
/// Iterator Design Pattern
/// </summary>
public class Program
{
public static void Main(string[] args)
{
ConcreteAggregate a = new ConcreteAggregate();
a[0] = "Item A";
a[1] = "Item B";
a[2] = "Item C";
a[3] = "Item D";
// Create Iterator and provide aggregate
Iterator i = a.CreateIterator();
Console.WriteLine("Iterating over collection:");
object item = i.First();
while (item != null)
{
Console.WriteLine(item);
item = i.Next();
}
// Wait for user
Console.ReadKey();
}
}
/// <summary>
/// The 'Aggregate' abstract class
/// </summary>
public abstract class Aggregate
{
public abstract Iterator CreateIterator();
}
/// <summary>
/// The 'ConcreteAggregate' class
/// </summary>
public class ConcreteAggregate : Aggregate
{
List<object> items = new List<object>();
public override Iterator CreateIterator()
{
return new ConcreteIterator(this);
}
// Get item count
public int Count
{
get { return items.Count; }
}
// Indexer
public object this[int index]
{
get { return items[index]; }
set { items.Insert(index, value); }
}
}
/// <summary>
/// The 'Iterator' abstract class
/// </summary>
public abstract class Iterator
{
public abstract object First();
public abstract object Next();
public abstract bool IsDone();
public abstract object CurrentItem();
}
/// <summary>
/// The 'ConcreteIterator' class
/// </summary>
public class ConcreteIterator : Iterator
{
ConcreteAggregate aggregate;
int current = 0;
// Constructor
public ConcreteIterator(ConcreteAggregate aggregate)
{
this.aggregate = aggregate;
}
// Gets first iteration item
public override object First()
{
return aggregate[0];
}
// Gets next iteration item
public override object Next()
{
object ret = null;
if (current < aggregate.Count - 1)
{
ret = aggregate[++current];
}
return ret;
}
// Gets current iteration item
public override object CurrentItem()
{
return aggregate[current];
}
// Gets whether iterations are complete
public override bool IsDone()
{
return current >= aggregate.Count;
}
}
}
This real-world code demonstrates the Iterator pattern which is used to iterate over a collection of items and skip a specific number of items each iteration.
using System;
using System.Collections.Generic;
namespace Iterator.RealWorld
{
/// <summary>
/// Iterator Design Pattern
/// </summary>
public class Program
{
public static void Main(string[] args)
{
// Build a collection
Collection collection = new Collection();
collection[0] = new Item("Item 0");
collection[1] = new Item("Item 1");
collection[2] = new Item("Item 2");
collection[3] = new Item("Item 3");
collection[4] = new Item("Item 4");
collection[5] = new Item("Item 5");
collection[6] = new Item("Item 6");
collection[7] = new Item("Item 7");
collection[8] = new Item("Item 8");
// Create iterator
Iterator iterator = collection.CreateIterator();
// Skip every other item
iterator.Step = 2;
Console.WriteLine("Iterating over collection:");
for (Item item = iterator.First();
!iterator.IsDone; item = iterator.Next())
{
Console.WriteLine(item.Name);
}
// Wait for user
Console.ReadKey();
}
}
/// <summary>
/// A collection item
/// </summary>
public class Item
{
string name;
// Constructor
public Item(string name)
{
this.name = name;
}
public string Name
{
get { return name; }
}
}
/// <summary>
/// The 'Aggregate' interface
/// </summary>
public interface IAbstractCollection
{
Iterator CreateIterator();
}
/// <summary>
/// The 'ConcreteAggregate' class
/// </summary>
public class Collection : IAbstractCollection
{
List<Item> items = new List<Item>();
public Iterator CreateIterator()
{
return new Iterator(this);
}
// Gets item count
public int Count
{
get { return items.Count; }
}
// Indexer
public Item this[int index]
{
get { return items[index]; }
set { items.Add(value); }
}
}
/// <summary>
/// The 'Iterator' interface
/// </summary>
public interface IAbstractIterator
{
Item First();
Item Next();
bool IsDone { get; }
Item CurrentItem { get; }
}
/// <summary>
/// The 'ConcreteIterator' class
/// </summary>
public class Iterator : IAbstractIterator
{
Collection collection;
int current = 0;
int step = 1;
// Constructor
public Iterator(Collection collection)
{
this.collection = collection;
}
// Gets first item
public Item First()
{
current = 0;
return collection[current] as Item;
}
// Gets next item
public Item Next()
{
current += step;
if (!IsDone)
return collection[current] as Item;
else
return null;
}
// Gets or sets stepsize
public int Step
{
get { return step; }
set { step = value; }
}
// Gets current iterator item
public Item CurrentItem
{
get { return collection[current] as Item; }
}
// Gets whether iteration is complete
public bool IsDone
{
get { return current >= collection.Count; }
}
}
}
The .NET optimized code demonstrates the
same real-world situation as above but uses modern, built-in .NET features,
such as, generics, reflection, LINQ, lambda functions, etc.
You can find an example on our Singleton pattern page.
All other patterns (and much more) are available in our Dofactory .NET product.
Not only does Dofactory .NET cover the Gang of Four and Enterprise patterns, it also includes
pattern architectures, low-code, and RAD (Rapid Application Development) techniques.
Accelerate development to where you can write
entire solutions in just 33 days!.
This unique package will change your developer lifestyle.
Here's what is included: