.NET Design Patterns

Iterator


 Definition
 UML diagram
 Participants
 Structural code in C#
 Real-world code in C#
 .NET Optimized code in C#



Definition

Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

Frequency of use:
High




UML class diagram






Participants


    The classes and objects participating in this pattern are:

  • Iterator  (AbstractIterator)
    • defines an interface for accessing and traversing elements.
  • ConcreteIterator  (Iterator)
    • implements the Iterator interface.
    • keeps track of the current position in the traversal of the aggregate.
  • Aggregate  (AbstractCollection)
    • defines an interface for creating an Iterator object
  • ConcreteAggregate  (Collection)
    • implements the Iterator creation interface to return an instance of the proper ConcreteIterator



Structural code in C#


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;

 

namespace DoFactory.GangOfFour.Iterator.Structural

{

    /// <summary>

    /// MainApp startup class for Structural

    /// Iterator Design Pattern.

    /// </summary>

    class MainApp

    {

        /// <summary>

        /// Entry point into console application.

        /// </summary>

        static void Main()

        {

            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

            ConcreteIterator i = new ConcreteIterator(a);

 

            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>

    abstract class Aggregate

    {

        public abstract Iterator CreateIterator();

    }

 

    /// <summary>

    /// The 'ConcreteAggregate' class

    /// </summary>

    class ConcreteAggregate : Aggregate

    {

        private ArrayList _items = new ArrayList();

 

        public override Iterator CreateIterator()

        {

            return new ConcreteIterator(this);

        }

 

        // Gets 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>

    abstract class Iterator

    {

        public abstract object First();

        public abstract object Next();

        public abstract bool IsDone();

        public abstract object CurrentItem();

    }

 

    /// <summary>

    /// The 'ConcreteIterator' class

    /// </summary>

    class ConcreteIterator : Iterator

    {

        private ConcreteAggregate _aggregate;

        private 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;

        }

    }

}


Output
Iterating over collection:
Item A
Item B
Item C
Item D




Real-world code in C#


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;

 

namespace DoFactory.GangOfFour.Iterator.RealWorld

{

    /// <summary>

    /// MainApp startup class for Real-World

    /// Iterator Design Pattern.

    /// </summary>

    class MainApp

    {

        /// <summary>

        /// Entry point into console application.

        /// </summary>

        static void Main()

        {

            // 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 = new Iterator(collection);

 

            // 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>

    class Item

    {

        private string _name;

 

        // Constructor

        public Item(string name)

        {

            this._name = name;

        }

 

        // Gets name

        public string Name

        {

            get { return _name; }

        }

    }

 

    /// <summary>

    /// The 'Aggregate' interface

    /// </summary>

    interface IAbstractCollection

    {

        Iterator CreateIterator();

    }

 

    /// <summary>

    /// The 'ConcreteAggregate' class

    /// </summary>

    class Collection : IAbstractCollection

    {

        private ArrayList _items = new ArrayList();

 

        public Iterator CreateIterator()

        {

            return new Iterator(this);

        }

 

        // Gets item count

        public int Count

        {

            get { return _items.Count; }

        }

 

        // Indexer

        public object this[int index]

        {

            get { return _items[index]; }

            set { _items.Add(value); }

        }

    }

 

    /// <summary>

    /// The 'Iterator' interface

    /// </summary>

    interface IAbstractIterator

    {

        Item First();

        Item Next();

        bool IsDone { get; }

        Item CurrentItem { get; }

    }

 

    /// <summary>

    /// The 'ConcreteIterator' class

    /// </summary>

    class Iterator : IAbstractIterator

    {

        private Collection _collection;

        private int _current = 0;

        private 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; }

        }

    }

}


Output
Iterating over collection:
Item 0
Item 2
Item 4
Item 6
Item 8




.NET Optimized code in C#


The .NET optimized code demonstrates the same real-world situation as above but uses modern, built-in .NET features, such as, generics, reflection, object initializers, automatic properties, etc. You can find an example on our Singleton pattern page.

All other patterns (and much more) are available in our .NET Design Pattern Framework 4.5.


Not only does the .NET Design Pattern Framework 4.5 cover GOF and Enterprise patterns, it also includes .NET pattern architectures that reduce the code you need to write by up to 75%. This unique package will change your .NET lifestyle -- for only $79.  Here's what is included:



  • 69 gang-of-four pattern projects
  • 46 head-first pattern projects
  • Fowler's enterprise patterns
  • Multi-tier patterns
  • Convention over configuration
  • Active Record and CQRS patterns
  • Repository and Unit-of-Work patterns
  • MVC, MVP, & MVVM patterns
  • REST patterns with Web API
  • SparkTM Rapid App Dev (RAD) platform!
  • Art Shop MVC Reference Application
  • 100% pure source code