Monday, December 27, 2010

State and CycledEnumerator

The GoF State pattern is not on top of my list of favorites (Decorator is), but I am using it from time to time. And as you probably are aware there is this question about the implementation of State: whoever will switch between states and when?

I thought that Iterator -- another GoF pattern -- might be a good example of something that encapsulates state switching logic in some cases, when the states are switched strictly in the order you know beforehand. I realize that not every State implementation is that simple, but if yours is, you might want to use the idea: just pass the IEnumerable of IState to the implementation of State, and use MoveNext() and Current {get;} on the Enumerator internally to switch states. If you are doing something like this, it might be a good idea to jump back to State #1 after you've reached State #Last. I've written a little helper class to do just that:

using System;
using System.Collections.Generic;

namespace Primitives
{
    public class CycledEnumerator<T> : IEnumerator<T>
        where T : class
    {
        private LinkedList<T> _chainedObjects;
        private LinkedListNode<T> _currentObject;

        public CycledEnumerator(IEnumerable<T> objectsToChain)
        {
            if (objectsToChain == null)
            {
                throw new ArgumentNullException("objectsToChain");
            }

            _chainedObjects = new LinkedList<T>(objectsToChain);

            if (_chainedObjects.Contains(null))
            {
                throw new ArgumentException("Nulls are not allowed.", "objectsToChain");
            }

            if (_chainedObjects.Count < 1)
            {
                throw new ArgumentException("Need at least one item in the set.", "objectsToChain");
            }

            this.MoveBeforeFirstElement();
        }

        private void MoveBeforeFirstElement()
        {
            _currentObject = null; // I don't like nulls at all, but I'm putting it here for the sake of consistency with Microsoft's implementations of Enumerator (which is a variant of GoF Iterator pattern).
        }

        public T Current
        {
            get
            {
                return _currentObject.Value;
            }
        }

        public void Dispose()
        {
        }

        object System.Collections.IEnumerator.Current
        {
            get
            {
                return _currentObject;
            }
        }

        public bool MoveNext()
        {
            if ((_currentObject == null) || (_currentObject.Next == null))
            {
                MoveToFirstElement();
            }
            else
            {
                _currentObject = _currentObject.Next;
            }

            return true;
        }

        private void MoveToFirstElement()
        {
            _currentObject = _chainedObjects.First;
        }

        public void Reset()
        {
            this.MoveBeforeFirstElement();
        }
    }
}

(That said, I don't like Iterator much (and all of its buddies, like the Enumerator): it exposes too much of its state to the client, and has too complex a contract. It's all like "if MoveNext() returns true, then Current contains the next element", or: "after initialization the Enumerator is positioned before the first element, and you should call MoveNext() to get anything from it".)

Gang Of Four Patterns

Some days I find myself really believing that Gang Of Four patterns describe about 90% of all domain-model-related software design tasks out there. On our last design meeting I only had to name the applicable patterns, and that about did it: "Huh, this can be done with a Visitor", or "Sounds like an ordinary Composite to me"... That is not to say I'm good, but rather to reiterate what this guy told me once: "Everything has already been written".

("Design Patterns: Elements of Reusable Object-Oriented Software" was one of the first books I've read on the subject, years ago, and it's a really good read.)