Runtime flexibility and future proofing; GOF BEHAVIOURAL Patterns with C# - Part 3 - by Barry Mossman

By: Barry Mossman

Abstract: This is the fifth and final article in a series upon the GOF Design patterns from a C# and .Net Framework perspective. It is a continuation of the BEHAVIORAL Patterns, this time looking at the State, Strategy, Template and Visitor patterns.

Final runtime flexibility and future proofing; part 3 of GOF Behavioural Patterns with C#

BarryMossman<is_at>primos.com.au

This is my fifth, and final, article looking at the GOF Design patterns. Earlier articles studied the Creational Patterns, Structural Patterns and began examination of the Behavioural Patterns. This one looks at the final Behavioural Patterns. There are links to my earlier articles at the bottom of this one. This articles covers the following patterns:

  • State, Strategy, Template Method, Visitor

The source for this article's demonstration program is available at CodeCentral. See the link at the bottom of this document.

The first article (Creational Patterns) also gave an overview of where the patterns came from, and the general discussion of the general techniques that they promoted. I will firstly briefly recap a few of the points from that article.

The GOF design patterns help address the following challenges :

    • design ready to accommodate change & growth

    • design flexible systems that come ready to handle reconfiguration and run time tailoring

    • code in manner to facilitate reuse during the development and extension phases ... ie. both external and internal reuse, so that we are rewarded by efficiencies as the project progresses, coming for investments made earlier in the project.

    • implement change in a way that doesn't overly shorten the system's useful lifespan

In a multi-person project the design patterns have the additional utility of providing a shorthand language with which to describe design options and specifications.

The design patterns were defined in the programming classic entitled "Design Patterns" by Gamma, Helm, Johnson & Vlissides. The four authors are commonly described as the Gang Of Four (GOF) for brevity. The subtitle of the book is "elements of reusable object-oriented software". There is a link to this book at the end of this document.

One of the book's key points is that the authors favour using "object composition" over "class inheritance" when designing our system's objects. This means that our objects are assembled at runtime from a number of helper classes working together to deliver the desired behaviour, rather than being statically defined at compile time using class inheritance. Objects that are created in this way offer a great deal of runtime flexibility, and are better set up for future modification. A general theme of the Behavioural patterns is that they allow the composition of larger and more flexible structures from smaller helper classes.

The approach necessitates more physical classes, but is made more workable where patterns are used as they help to bring an understandable structure to the design. The fact that the patterns are based upon system design structures that have been tested and refined over time is also of assistance.

Note that the advice is to only to "favour" object composition over class inheritance, not to stop using inheritance altogether. The two techniques work well together



A summary of the patterns

Pattern Name

General Objective

State

This pattern is applicable for objects that need to be able to change between various states, and where the object needs to have differing behaviours for the different states.

Strategy

This pattern allows us to encapsulate algorithms as classes in order to make them reusable, interchangeable or just hidden from the client.

Use of this pattern can help achieve the goal of having an application comprised of loosely coupled interchangeable parts, avoiding an overly monolithic implementation of our application.

The pattern can help to reduce the amount of subclassing required in some circumstances.

Template

The Template pattern permits us to offer flexibility and achieve reuse within application algorithms, while still being able to retain control over those elements of the algorithm which we want to run unchanged.

The pattern is related to the Strategy pattern. Where the Strategy pattern used delegation to vary the whole algorithm, the Template pattern allows inheritance to specify variation to portions of a flexible base algorithm

Visitor

In this pattern we design a class, or group of classes, to be independent of the operations that will be performed upon it. The operations are collected together into a separate Visitor class, and the target classes (Elements) are designed to be "visitor ready”.

Use of this pattern can reduce the impact of future system changes, and can aid with source code organisation by having common types of Operation grouped together within the Visitor class.


The following Behavioural Patterns have already been covered in an earlier article (see link at bottom of this article)

Pattern Name

General Objective

Chain of Responsibility

Allows us to decouple a client's request for action, from the class that will implement it.

The client builds a chain of candidate classes (Handlers) to handle the request, and then passes the request to the chain. The client is simplified as it does not need to know which class will finally handle the request. The request is passed down the chain, one handler at a time, until one of them accepts responsibility for the request.

There is much flexibility as the chain is built at runtime, and the sequence can therefore be tailored by runtime or configuration conditions.

Command

Allows us to make commands, or requests against an object, into objects themselves.

Potential OO benefits include grouping of command series into macros, providing undo support, facilitating command logging, persisting commands or macros via Save|Restore, queuing commands for later execution, and runtime tailoring of commands that are to be executed.

Interpreter

This pattern enables us to design a script language, it's syntax, and then implement an Interpreter to process requests that have been recorded in that language.

This allows us to create a flexible client that is capable of receiving and actioning high level request scripts written in a command language that we have designed to suit the users of our system.

Iterator

Outsource the task of iteration through an aggregate members into a separate class.

Allows generic navigation code able to address different aggregate classes. Client can open simultaneous independent cursors into a single aggregate instance, or an aggregate class can offer alternate methods of navigation without cluttering it's implementation or public interface.

Mediator

Collect the rules of interaction between a number of classes (Colleagues), and encapsulate them into a separate Mediator class.

Simplify our application's big picture since the cooperation of the Colleague classes is collected together into the one place.

Can facilitate more reuse, and reduce the disruption caused by future enhancement. For example a new class of Mediator reusing Colleagues working together in a new way, or new Colleagues which could be coordinated in a familiar fashion by an old Mediator class.

Observer

This pattern allows a number of Observer classes to observe, and synchronize themselves to, the state of a Subject class.

Allows cohesion without tight coupling. Enables independent reuse, or enhancement of, Subjects or Observers.

Introduces flexibility as Observers can be added or removed at runtime, or subsequent versions could introduce new Observer classes with minimal disruption.

Memento

This pattern allows us to save, or restore, an object's internal state without violating it's encapsulation.

Addresses security considerations regarding information held within the Momento, also may deployed such that only the object that created the Momento can use it for restoration..



State Pattern

This pattern is applicable in a situation where our application needs a class whose objects can change between various States (eg between Open, Closed, Readonly etc), and the object's behaviour is determined by it's current state. The pattern provides a means of catering for the differing state behaviours using polymorphism rather than using messy switch or if/else blocks everywhere throughout the program.

The class, that needs the differing state behaviours, is called the Context. It's state-dependant behaviours are provided by a behind-the-scenes State class.

Benefits of the State pattern:

  • behaviour for any specific state is collected together, and can be understood without having to search through the whole class looking for "switch" and "if" logic blocks.

  • it should be easier to introduce a new state later, than in a situation where state dependant behaviour logic was wide spread

  • the Context's state is "atomic", ie. it can never have an invalid internal state, as could occur if the transition from one state to another involved more than flicking a single flag.

There are some deployment options with the State pattern:

  • the State objects could be created as Singletons. Suitable if the Context objects will be changing state frequently. The State classes would need to provide only logic, ie. have no state of their own as they would be shared if there were multiple Context objects in operation at the one time. (see coverage of Singleton's in the Creational Patterns article in the links section at the bottom of this article).

  • The Context object can be responsible for switching between states. ...Decouples the state classes from each other.

  • Or we can make the helper State objects responsible for detecting the need for a state change, and for determining which state to switch to next. Will make it easier to add further states later.

In my demonstration program's we need to imagine that the Context objects are describing sa vehicle which is used to transport some kind of material. A Context object (vehicle) is in any one of the following states:

  • Loading : At the Loading Dock.

  • Unloading : At the Unloading Dock, not fully unloaded yet.

  • Empty : Still at the Unloading Dock, but now empty

  • Repairing : At the Repair Shop.

  • Intransit : Intransit between the Loading, Unloading or Repair areas.




The preceeding State diagram was produced by the free tool called UMLet (see link at the bottom of this article).

In this example we can best see the State pattern's deliverables by looking at the Context's Despatch method. The client uses this method to cause the context to enter the Intransit state, however the behaviour of this method needs to change depending upon the current Context object's current state:

  • Loading : Despatch not allowed if the object has no load, unless the Context is flagged for repair. By default Despatch will cause the context to go Intransit heading towards Unloading, however if the Context has been flagged for repair, and has no load, it will go Intransit heading towards to Repairing.

  • Unloading : Despatch not allowed until the Context enters the Empty state.

  • Empty : Can be Despatched. Will go to Intransit towards Loading unless the Context is flagged for repair, in which case it will go towards Repairing.

  • Repairing : Despatch only allowed if repair is complete. Will go to Unloading.

  • Intransit : Despatch disallowed.

The State pattern handles this kind of requirement via polymorphism. Each concrete helper State class would override the Despatch method to provide behaviour appropriate to the Context's current state. The pattern has made it easy to see an overview of the Context's behaviour when it is a specific state. For example, in my demonstration program we will be able to see that the Loading state allows the Load method, and that it also allows it's own version of the Despatch method. We would be able to easily see that the Repairing state also allows the Despatch method, but with different rules. The Repairing state doesn't have the Loading method, but it does have a method to record that the repair job is complete. ... This overview picture would have been obscured if we had implemented this application requirement without the State pattern, as a State's behaviour would become the sum of a series of switch and if blocks spread throughout the Context class.

The State pattern should make it easy to introduce a new status named FULL at some time in the future. The Empty status could be used to show that the Context has completed Loading and is ready for Despatch. We would only need to change the Load State to monitor whether the Context was full, just as we determine whether it is empty. We would probably modify the Load Status's Despatch method so that it could no longer access the Despatch method, as this would be deferred to the new Empty state. ... Thanks to the State pattern we haven't had to search through the whole Context class looking things that may be affected by this new state that we are introducing.

My implementation of the State pattern uses the deployment options to use shareable singleton State objects, and to outsource the need for triggering of state changes to the State classes themselves.

Here is the output from my demonstration run:




The client uses two service methods to display the Context's status for the purposes of demonstration:

    private void ShowStatus1(Context aContext, RichTextBox testOutput) {
            testOutput.AppendText(String.Format(
                "nStatus = {1}: Content = {0}, Repair requested ? = {2}n",
                aContext.AmountLoaded, aContext.CurrentState.ToString(),
                aContext.NeedsRepair));
    }

    private void ShowStatus2(Context aContext, int aUnLoadRequest, 
                             int aUnloadAchieved, RichTextBox testOutput) {
            testOutput.AppendText(String.Format(
                "nStatus = {1}; Requested {2}, given {3}, Content now = {0}.n",
                aContext.AmountLoaded, aContext.CurrentState.ToString(),
                aUnLoadRequest, aUnloadAchieved));
    }

The client code is as follows. Notice that the calls to the Despatch method: have no arguments, the differing behaviour is coming from polymorphism.

        Context context = new Context();

        // Load 80 units, then display status.
        ShowUserCommentary(1);
        context.Load(80);
        ShowStatus1(context, listBox1);

        /* Despatch loaded object, then display it's changed status
           (= Intransit) */
        ShowUserCommentary(2);
        context.Despatch();
        ShowStatus1(context, listBox1);

        // Receive the loaded object, then unload 30 units and display status
        ShowUserCommentary(3);
        context.Arrival();
        int unloadRequest = 30;
        int unloadAchieved = context.Unload(unloadRequest);
        ShowStatus2(context, unloadRequest, unloadAchieved, listBox1);

        /* Attempt to despatch the object. Will fail as the Despatch
           operation is not valid while the object is in the UNLOADING state.*/ 
        ShowUserCommentary(4);
        try {
                context.Despatch();
        }
        catch (ApplicationException ex) {
                listBox1.AppendText(String.Format(
                                    "nException raised: {0}n",ex.Message));
        }

        /* try and unload a further 70 unit, receive just the 50 remaining.
        The object is now empty, causing it's state to change to EMPTY */  
        ShowUserCommentary(5);
        unloadRequest = 70;
        unloadAchieved = context.Unload(unloadRequest);
        ShowStatus2(context, unloadRequest, unloadAchieved, listBox1);
        /* Despatch is now allowed. Process it's Arrival. We will be in
        Loading state again. */  
        ShowUserCommentary(6);
        context.Despatch();
        context.Arrival();
        ShowStatus1(context, listBox1);

        /* Flag the need for repair. Despatch the object. This time It will
           be routed to the Repair Shop, if it there were any loaded contents
           it would have gone to the Unloading bay first. */
        ShowUserCommentary(7);
        context.RequestRepair();
        context.Despatch();
        context.Arrival(); 
        ShowStatus1(context, listBox1);

Now to the pattern implementation. Firstly we shall define a couple of enumerations to use as switch settings. One enumeration describes the possible states for a Context object, and the other describes the list of possible despatch destinations.

    public enum State{Loading, Unloading, Empty, Repairing, Intransit}
    internal enum Destination{None, Loading, Unloading, Repairing}

Then we shall look at the base class for the State helper classes. It is an abstract class which provides method signatures for the Context to use internally for all of the state dependant methods such as Load and Despatch. It is also provides the behaviour that will be used if the client tries to use a method that is not supported by the Context's current State; in the case of my demonstration I just throw an exception.

    /* ================================
    Base class for the Context's States
    ================================ */
    abstract public class StateBase {
        // fields
        // properties
                abstract public State OurState {get;}
        // constructors
        protected StateBase () {}
        // methods
        /* The Context's state dependant behaviour is implemented by our
           sub-classes. If a sub-class does not override one of the following
           methods this means that State of the Context class that the sub-class
           represents does not support the method. We therefore throw an
           exception as the attempt to use a method that is unsupported by the
           state is a bug. */
        virtual internal bool Despatch(Context aContext, 
                                       ref Destination aDestination) {
            InvalidCallForState("Despatch");
            return false; // just to keep compiler happy
        }
        virtual internal void Arrival(Context aContext, 
                                      ref Destination aDestination) {
            InvalidCallForState("Arrival");
        }
        virtual internal bool Load(int aLoadQuantity,
                                   Context aContext, ref int aCurrentLoad) {
            InvalidCallForState("Load");
            return false; // just to keep compiler happy
        }
        virtual internal int Unload(int aQuantityRequested,
                                    Context aContext, ref int aCurrentLoad) {
            InvalidCallForState("Unload");
            return 0; // just to keep compiler happy
        }
        virtual internal void RepairCompleted(ref bool aRepairFlag) {
            InvalidCallForState("RepairCompleted");
        }
        private void InvalidCallForState(string aCallName) {
            throw new ApplicationException(
                String.Format("{0} method not supported when Context in {1}",
                              aCallName,this.ToString()));
        }
    }

There will be singleton concrete State classes for each of the Context's states as we shall see later, but firstly let us look at how the State helper classes are going to be used within the Context class. Here are the relevant sections from within the Context type. We can see that it's current state is recorded by a private field that will reference the singleton instance of one of the concrete State classes. The Context's constructor initialises the context to being in "Loading" state. Then finally there are the public signatures for the methods whose behaviour is state dependant. Each of these methods will utilise methods belonging to the State helper object that is referenced by the private field mentioned above.

        // fields
        /* the _state field determines the Context object's state. It refers
           to a singleton instance of one of the StateBase's concrete
           sub-classes. These classes implement state-dependant behaviour. */
        private StateBase _state;

        // constructors
        public Context() {
            /* set initial state to "Loading". There is a singleton instance for
               each of the possible states. */
            _state = Loading.Instance;
        }

        // methods
        /* ------- The following group of methods have state dependant
           implementations. The implementation is within concrete
           sub-classes of the Statebase type ------------------ */
        public bool Load(int aLoadQuantity) {
            return _state.Load(aLoadQuantity, this, ref _amountLoaded);
        }
        public int Unload(int aQuantityrequested) {
            return _state.Unload(aQuantityrequested, this, ref _amountLoaded);
        }
        public bool Despatch() {
            return _state.Despatch(this, ref _destination);
        }
        public void Arrival() {
            _state.Arrival(this, ref _destination);
        }
        public void RepairCompleted() {
            _state.RepairCompleted(ref _needsRepair);
        }

Here is the remainder of the Context class. I have snipped out the members that we have just covered above. The majority of this code is just related to my demonstration, rather than being part of the State pattern. The exception is the ChangeState method. My demonstration illustration of the State pattern uses the deployment option where the helper State objects are responsible for detecting the need for a state change, and for determining which state to switch to. Our current state's helper object (referred to by the _state field) will use this method if it determines that we need to change state.

    public class Context {
        // fields
        private int _amountLoaded;
        private bool _needsRepair = false;
        private Destination _destination = Destination.None;
        // properties
        public int AmountLoaded {
                get {return _amountLoaded;}
        }
        public bool NeedsRepair {
                get {return _needsRepair;}
                }
        public State CurrentState {
                get {return _state.OurState;}
        }
        // methods
        public void RequestRepair() {
            _needsRepair = true;
        }

        /* Method used to cause a transition from one Context state to another.
           The need for state transition is detected is detected by the
           State helper object pointed to by the _state field. It is that
           State helper object that calls this method. */
        internal void ChangeState(State aNextState) {
            switch (aNextState) {
            case State.Unloading:
                _state = Unloading.Instance;
                break;
            case State.Intransit:
                if (_destination == Destination.None)
                    throw new ApplicationException(
                        "Despatch called without a valid Destination.");
                _state = Intransit.Instance;
                break;
            case State.Loading:
                _state = Loading.Instance;
                break;
            case State.Empty:
                _state = Empty.Instance;
                break;
            case State.Repairing:
                _state = Repairing.Instance;
                break;
            }
        }
    }

Finally we shall look at the concrete State classes. As mentioned above I have implemented these using the Singleton pattern using the technique that was described in my article upon the GOF's Creation patterns (see links section at the bottom of this article). Singleton objects are stateless and shareable.

This implementation will cause a single reusable, and shareable, object to be created for each of the Context's states by the first use of that state by our application instance. Any subsequent use of that same state by the same, or any other Context object within the application, will reuse and share the same State helper object. This will mean that switching between states will be very efficient. Here is part of the concrete class for the Loading state. The following snippet shows the members that are associated with the Singleton behaviour of the class.

    /* ================================
    Loading State  (one of the possible states of the Context class)
        ================================ */
        public class Loading: StateBase {
        // fields
        private static readonly Loading singletonLoading = new Loading();
        // properties
        public static Loading Instance {
                        get {return singletonLoading;}
        }
        public override State OurState {
                        get {return State.Loading;}
        }
        // constructors
        private Loading() {}  // private, so unavail for outside use.
    }

Then there are the members for the Loading class that are associated with my demonstration program. Since the helper class for each state is shareable between Context objects, it can have no state of it's own. It will need to refer back to the Context object that it is assisting wherever it needs to deal with instance data.

From the Loading class's members following we can see that the Loading state only supports the Despatch and Load methods. If the client attempts to use any of the other state dependant methods the base class will issue an exception as the base behaviour has not been overridden by this concrete class. We can see from the following that the Loading state's Despatch behaviour is to disallow the despatch of empty vehicles unless they are flagged for repair. Vehicles are dispatched back towards the Loading Bay, unless they are both flagged for repair and empty.

        // methods
        override internal bool Despatch(Context aContext,
                                        ref Destination aDestination) {
                if ((aContext.AmountLoaded == 0) & (!aContext.NeedsRepair))
                return false;

                aDestination =
                        ((aContext.NeedsRepair) & (aContext.AmountLoaded == 0)) ?
                        Destination.Repairing:
                        Destination.Unloading;

                aContext.ChangeState(State.Intransit);
             return true;
        }
        override internal bool Load(int aLoadQuantity,
                                    Context aContext, ref int aCurrentLoad) {
            if (aContext.NeedsRepair)
                return false;
            else {
                aCurrentLoad += aLoadQuantity;
                return true;
            }
        }

Here is the Unloading class. We can see that it does not support the Despatch method at all. Despatch is not allowed until the context enters the Empty state.

    /* ================================
    Unloading State  (one of the possible states of the Context class)
        ================================ */
        public class Unloading: StateBase {
        // fields
        private static readonly Unloading singletonUnloading = new Unloading();
        // properties
        public static Unloading Instance {
                get {return singletonUnloading;}
        }
        public override State OurState {
                get {return State.Unloading;}
        }
        // constructors
        private Unloading() {}  // private, so unavail for outside use.
        // methods
        override internal int Unload(int aQuantityRequested,
                                     Context aContext, ref int aCurrentLoad) {
            int retval;
            if (aQuantityRequested < aCurrentLoad) {
                aCurrentLoad -= aQuantityRequested;
                retval = aQuantityRequested;
            } else {
                retval = aCurrentLoad;
                aCurrentLoad = 0;
                aContext.ChangeState(State.Empty);
            }
            return retval;
        }
    }       

Finally here is the Empty state. We can see that the Dispatch method is supported now, but it has different behaviour to that seen in the Loading state. The destination is now the Loading bay, unless the vehicle is in need of repair in which case it goes to the Repair Shop.

    /* ================================
    Empty State  (one of the possible states of the Context class)
    ================================ */
    public class Empty: StateBase {
          // fields
          private static readonly Empty singletonEmpty = new Empty();
          // properties
          public static Empty Instance {
                get {return singletonEmpty;}
          }
          public override State OurState {
                get {return State.Empty;}
          }
          // constructors
          private Empty() {}  // private, so unavail for outside use.
          // methods
          override internal bool Despatch(Context aContext,
                                          ref Destination aDestination) {
              if (aContext.AmountLoaded != 0)
                  return false;

                aDestination = (aContext.NeedsRepair)?
                             Destination.Repairing:
                             Destination.Loading;
              aContext.ChangeState(State.Intransit);
              return true;
          }
    }

I won't labour the point by showing the implementation of the Repairing and Intransit states here, although they are in my demonstration program if you wish to see them.

Strategy Pattern

This pattern allows us to encapsulate algorithms into classes in order to make them reusable, interchangeable or just hidden from the client. This helps us towards a goal of having an application comprised of loosely coupled interchangeable parts, and to avoid an overly monolithic implementation of our application.

An object (Context ) can be given a selection of helper objects (Strategies) to achieve it's ends. The helper Strategy objects all have the same interface, so the client can chose which helper class it wants to use at runtime. The algorithm that is achieving some aspect of the Context's behaviour is outsourced to the Strategy object(s).

The Strategy pattern could be applicable in the following situations:

  • we need differing versions of an algorithm dependant upon run time or configuration conditions, and would like to avoid a lot of switch or if/else blocks.

  • we need a number of related classes that just differ in some aspects of their behaviour. We would save a lot of sub-classing if we could just use a generic class, but plug in the strategy applicable to the run time conditions

  • we have an algorithm that we want our context to use, but would like it to be kept private from the context for some reason.

My demonstration program's illustration of the Strategy pattern has a Context class which can examine a document, and return to us a list of all the words that immediately follow any given word. The Context class can choose between two strategies to achieve this; the first involves searching through the whole document looking for the chosen word, and the other strategy deploys a keyed search into a hashtable. Here is the program's output.




Firstly let us get the task of obtaining the word list from the document out of the way. This is not part of the Strategy pattern, but we need some data to work with. I use .Net's regular expression support to break the document into a collection of words after stripping off miscellaneous punctuation characters. The words are collected into a specialist MatchCollection class, with collection entries of type Match. Here is a client method to complete this task:

        /* Obtain some data to demonstrate with. The data will be the
           collection of words found in a text file */
        private MatchCollection GetSomeData() {
                Regex regex = new Regex(
                                        @"[^s.,""-()]   # discard non-words
                                        w*                   # capture words",
                                        RegexOptions.IgnoreCase
                                        | RegexOptions.Multiline
                                        | RegexOptions.IgnorePatternWhitespace
                                        );
                workListBox = new RichTextBox();
                const string fileName = "Flyweight words.rtf";
                try {
                        workListBox.LoadFile(fileName);
                }
                catch (System.IO.FileNotFoundException e) {
                        throw new ApplicationException(String.Format
                              ("File "{0}" is needed by this demonstration; {1}",
                              fileName, e.Message));
                }

                return regex.Matches(workListBox.Text);
        }

Next we shall look at the client code that produces the above output. Firstly we obtain some data, then create a Context object that will use the "array" strategy in the first instance. We analyse the document using this strategy, and then change strategies to use the same client code to analyse the document with the "hashtable" strategy. The "Load" method is called for the new strategy because each strategy has it's own version of the Load method. The service method named "FindAndDisplayNeighbours" will be shown in the code snippet following this one.

        MatchCollection data = GetSomeData();

        Context context = new Context(new ConcreteStrategyUseArray());
        context.LoadData(data);

        /* Analyse document to find the list of all words that
           immediately follow the search word in the document that we
           loaded into the context. */
        ShowUserCommentary(1);
        FindAndDisplayWordNeighbours(context,"Philippe");
                               
        FindAndDisplayWordNeighbours(context,"the");

        /* Change to a different strategy. The above strategy searched
           through an internal arraylist to find the neighbour words. This
           new strategy uses keyed searches into a hashtable. */
        ShowUserCommentary(2);
        context.ChangeStrategy(new ConcreteStrategyUseHashtable());
        context.LoadData(data);
                        
        FindAndDisplayWordNeighbours(context,"Philippe");
                               
        FindAndDisplayWordNeighbours(context,"the");

Finally for the client we shall look at the FindAndDisplayNeighbours service method. The Context is asked for the list of "neighbouring" words. The Context will use the currently selected strategy to perform this task.

        /* Get, and print, the list of single words that immediately follow
           each occurrence of the search word in the document being analysed. */
        private void FindAndDisplayWordNeighbours(Context aContext, 
                                                  string aSearchWord) {
                string[] neighbourList = aContext.GetNeighbours(aSearchWord);

                StringBuilder sb = new StringBuilder("");
                for (int i = 0; i < neighbourList.Length ; i++)
                {
                        sb.Append(neighbourList[i] + " ");
                }

                listBox1.AppendText(String.Format(
                        "nThe word "{0}" is immediately followed by the the following words; {1}",
                        aSearchWord, sb.ToString()));
        }

Now to the pattern's implementation. The interface of the helper Strategy objects can be seen by looking at their base class. We can see that it is going to assist the Context with LoadData and GetNeighbours services.

        abstract public class StrategyBase {
                // methods
                abstract public void LoadData(MatchCollection aList);
                abstract public string[] GetNeighbours(string aWord);
        }

Next we shall look at the implementation of the Context class. We can see that it maintains a reference to the Strategy object that is currently helping it. Requests from the client are passed on to the Strategy object.

        public class Context {
                // fields
                private StrategyBase _strategy;
                // constructors
                public Context (StrategyBase strategy) {
                        _strategy = strategy;
                }
                // methods
                public void ChangeStrategy(StrategyBase strategy) {
                        _strategy = strategy;
                }
                // Load the document into an internal form suitable for searching.
                public void LoadData (MatchCollection aList) {
                        _strategy.LoadData(aList);
                }
                public string[] GetNeighbours(string aWord) {
                        return _strategy.GetNeighbours(aWord);
                }
        }

We don't need to study the concrete Strategy classes to understand the Strategy pattern, but the demonstration doesn't do much without them. This first strategy loads all the words from the document into an arraylist, and then scans through the list to pluck out all of the neighbours of the word being analysed.

     public class ConcreteStrategyUseArray: StrategyBase {
          // fields
          private string[] _wordList, _neighbourList;
          // methods
          /* load document into structures suitable for a search to find 
             any given word's "neighbours".
             Build two lists. one to contain all words (in lower case to
             make matching easier, and the other to contain the word's
             neighbour in the same relative array cell (case preserved). */
          override public void LoadData (MatchCollection aList){
               _wordList = new string[aList.Count];
               _neighbourList = new string[aList.Count];
               for (int i = 0; i < aList.Count; i++) {
                    _wordList[i] = (aList[i].ToString()).ToLower();
                    _neighbourList[i] = (i < (aList.Count-1))?
                                                 aList[i+1].ToString():"";
               }
          }

          /* Return the list of all neighbours of the word passed by
             parameter.*/
          override public string[] GetNeighbours(string aWord) {
               ArrayList workList = new ArrayList();
               int i = 0;
               int index = 0;
               // look at whole document
               do {
                    index = Array.IndexOf(_wordList, aWord.ToLower(), i);
                    if (index >= 0) {
                         workList.Add(_neighbourList[index]);
                         /* search will continue from beyond where 
                            we have just found the target word. */
                         i = index + 1;
                    }
               } while (index >= 0);

               string[] retval = new string[workList.Count];
               workList.CopyTo(retval);
               return retval;
          }
     }
        

Finally we have the strategy that employs a hashtable collection. We trade off a saving during the search phase, for a little more expense during the Load phase.

     public class ConcreteStrategyUseHashtable: StrategyBase {
          // fields        
              /* This field contains each word found in the document up to,
                 but not including, the document's last word.
                 The key for the first occurrence of the word is the word
                 itself in lower case.
                 The value is a comma separated list of the word that immediately
                 follows each coinsurance of the word within the document.
                 eg. if the document is "The cat sat on the mat."
                 Key        Value
                 ----       -----
                 the        cat,mat
                 cat        sat
                 sat        on
                 on         the                    */
          private Hashtable _neighbourList;
          // methods              
          /* load document into a structure suitable for a search to find any
             given word's "neighbours". */
          override public void LoadData (MatchCollection aList){
               _neighbourList = new Hashtable(aList.Count);

               StringBuilder neighbourWork;

               // process the whole document
               for (int i = 0; i < aList.Count-1; i++) {
                    // word comparison is not case sensitive
                    string word = aList[i].ToString().ToLower();
                    /* detect whether the document has already used the word
                       being examined.        */
                    if (_neighbourList.ContainsKey(word)) {
                            /* if so, then add the new neighbouring word 
                               into a comma separated list with those 
                               already recorded. */
                            neighbourWork = (StringBuilder)_neighbourList[word];
                            neighbourWork.AppendFormat
                                 (",{0}", aList[i+1].ToString());
                            _neighbourList[word] = neighbourWork;
                    }
                    else
                         // record the new word's neighbouring word
                         _neighbourList.Add
                              (word, new StringBuilder(aList[i+1].ToString()));
               }
           }

          // Return the list of all neighbours of the word passed by parameter.
          override public string[] GetNeighbours(string aWord) {
               string word = aWord.ToLower();
               string neighbours = "";

               /* get the comma separated list of neighbouring words if the
                  word being examined exists within the document. */
               if (_neighbourList.ContainsKey(word)) {
                       StringBuilder neighbourList = 
                            (StringBuilder)_neighbourList[word];
                       neighbours = neighbourList.ToString();
               }

               // return the list of neighbouring words in a string array.
               return (neighbours.Split(new Char [] {','}));


          }

Template Pattern

The Template pattern permits us to offer flexibility and achieve reuse within application algorithms, while still being able to retain tight control over those elements of the algorithm which we want to run unchanged.

In this pattern we define a base class to define the structure of an algorithm, while deferring some of the steps to concrete subclasses which will inherit from the base. The pattern runs using the "Hollywood principle" which is "Don't call us, we'll call you". This is because the base class retains control, as it calls subclass methods as required, rather than the usual arrangement where concrete sub-classes call the ancestor's "base" methods. We have therefore been able to ensure that some portions of the algorithm are run without change. The pattern allows us to avoid the bugs that could occur if an ancestor class neglected to call some essential part of the base specification of the algorithm.

The base class provides for variability within the algorithm in either of two ways:

  • a "hook" which allows a base method to be optionally overridden

  • an abstract method which must be overridden by the concrete sub-class

The pattern is related to the Strategy pattern. Where the Strategy pattern used delegation to vary the whole algorithm, the Template pattern allows inheritance to specify variation to portions of a flexible base algorithm.

My illustration of the Template pattern has a base algorithm which produces a timestamped message. The concrete subclasses inherit from the base algorithm, using it's basic structure and some of it's methods. They are required to provide their own time stamp format, and have the option of overriding a "hook" method that sets the font format for any part of the message which is enclosed within quotation marks.

Here is the illustration's client code:

        /* Use our template to produce a message. Any part of the message
           that is within quotation marks will be specially formatted,
           and a timestamp will be provided. */
        TemplateBase template = new ConcreteTemplate_1();

        ShowUserCommentary(1);
        listBox1.SelectedRtf = template.TemplateMethod(
                @"Brought to you by the ""Template "" pattern");

        // now use a variation upon the same algorithm to produce
        // a slightly different message.
        template = new ConcreteTemplate_2();

        ShowUserCommentary(2);
        listBox1.SelectedRtf = template.TemplateMethod(
                @"Brought to you by the ""Template "" pattern");

It produces the following output.




The interface for our Template pattern's base class could be described as follows, where TemplateMethod is the method called by the client to invoke the algorithm, and the other two methods are "primitive operations" that may be overridden by the concrete subclass that inherit from the base. The remainder of the algorithm is fixed, and will run as the original designer intended.

        public interface ITemplate {
                // template method; used by client
                string TemplateMethod ();
                // primitive methods; may be overridden by concrete sub-classes
                string GetDateMessage();
                void GetStyleForQuotes(out float aSize,
                        out FontStyle aStyle,
                        out Color aColor);
        }

Here is the implementation of the base class. The TemplateMethod is called by the client, and it drives the processing of the algorithm. It uses the GetDateMessage which is abstract, and therefore must be overridden by a concrete descendant to provide implementation. The TemplateMethod also uses the GetFormatingForQuotes method which has a default implementation, a concrete subclass may override this "hook method" if it wants a different implementation to the default one provided.

The algorithm parses a text string, and applies special formatting to any text found enclosed within quotation marks. It then appends a message timestamps, and passes the formatted string back to the client.

     // --- Base class
     abstract public class TemplateBase {
          // methods - template method; called by the client
          public string TemplateMethod () {
                float fontSize;
                FontStyle fontStyle;
                Color color;

                GetStyleForQuotes(out fontSize, out fontStyle, out color);
                string message = (@"Brought to you by the ""Template "" pattern"
                                  + @GetDateMessage());
                return
                    FormatMessage(message, fontSize, fontStyle, color);
          }
          // methods - primitive methods; used by the template message
          /*           The first is an abstract method requiring an override
                          by the concrete sub-class. The second is a "hook"
                          method, which may, or may not be overridden */
          abstract public string GetDateMessage();
          virtual public void GetStyleForQuotes(out float aSize,
                                                    out FontStyle aStyle,
                                                    out Color aColor) {
               aSize = 13;
               aStyle = FontStyle.Italic;
               aColor = Color.Blue;
          }
          // methods - other; service methods
          /*
          private string FormatMessage(string aMessage,
                                        float afontSize,
                                        FontStyle aFontStyle,
                                        Color aColor) {

               // create a richTextObject to format our message into RTF format
               RichTextBox rich = new RichTextBox();
               rich.SelectionColor = System.Drawing.Color.MediumBlue;
               Color saveColor = rich.SelectionColor;
               rich.AppendText("n");

               /* Divide message text into sets of leading unquoted material,
                  following by material contained within quote marks. */
               MatchCollection mc = BreakApartMessage(aMessage);

               // format the message for the client
               foreach (Match m in mc) {
                          GroupCollection gc = m.Groups;

                          if (gc["unquoted"].Length > 0) {
                                  rich.SelectionColor = saveColor;
                                  rich.AppendText(gc["unquoted"].Value);
                          }

                         int quotedLength = gc["quoted"].Length;
                           if (quotedLength > 0) {
                            rich.SelectionColor = aColor;
                                  Font currentFont = rich.SelectionFont;

                            rich.SelectionFont = new Font(
                                       currentFont.FontFamily,
                                       afontSize,
                                              aFontStyle);

                            rich.AppendText(gc["quoted"].ToString()
                                .Substring(0,(quotedLength-1)));
                                  rich.SelectionColor = saveColor;
                                  rich.SelectionFont = currentFont;
                                  rich.AppendText(@"""");
                           }
               }

               return rich.Rtf;
          }

          /* Break the message into sets of leading unquoted text, and text
             containing within quotation marks. */
          private MatchCollection BreakApartMessage(string aMessage) {
               Regex regex = new Regex(
                    @"(?<unquoted>[^""]*""?)?    # Text leading up to, and
                                                 # including an opening quote
                                                 # mark if there is one.

                    (?<quoted>[^""]*""{1})?      # Quoted text, and the closing
                                                 # quote mark. Include closing
                                                 # quote mark so we can don't
                                                 # capture all up to document
                                                 # end if there is an
                                                 # unmatchedquote mark.
                    ",
                                  RegexOptions.IgnoreCase
                                  | RegexOptions.Multiline
                                  | RegexOptions.IgnorePatternWhitespace
                             );

               return regex.Matches(aMessage);
          }
     }

Finally here are the two concrete subclasses. The first provides an override for the optional "hook" GetStyleForQuotes method.

     // --- Concrete sub-classes
     public class ConcreteTemplate_1: TemplateBase {
          // methods
          // optional override of template's "hook" method
          override public void GetStyleForQuotes(out float aSize,
                          out FontStyle aStyle,
                          out Color aColor) {
                  aSize = 20;
                  aStyle = FontStyle.Bold | FontStyle.Underline;
                  aColor = Color.Red;
          }
          // mandatory override of template's abstract method
          override public string GetDateMessage() {
                  return String.Format(" upon this {0:U}",DateTime.Now);
          }
     }

     public class ConcreteTemplate_2: TemplateBase {
          // fields
          private readonly DateTime _RutherfordPrize = 
               new System.DateTime      (1908,12,11);
          // methods
               override public string GetDateMessage() {
                    return String.Format(" upon this day, just {0:N0} days since Ernest Rutherford was awarded the Nobel Prize for work done upon the structure of the atom.",
                                System.DateTime.Now.Subtract(_RutherfordPrize).Days);
         }
     }

Visitor Pattern

In this pattern we make a class independent of the operations that can be performed upon it. The operations are then defined within their own separate Visitor classes. The class, or classes, upon which they can operate (Elements) are made "visitor ready" so that they can accept the Visitors.

The Visitor pattern can provide the following benefits:

  • a new operation can be provided without having to change all of the affected Element classes. All we need to do is create a new Visitor class.

  • all of the program logic for a specific operation is gathered together into it's own Visitor class, avoiding a situation where the operation logic is spread across each of the individual Element classes that the operation can affect.

The pattern is especially applicable in the following situations:

  • where the Element classes are beyond the control of the Programmer who will be tasked with adding, or changing, operations that will act upon the Element classes.

  • where the application will have multiple Element classes with differing interfaces, and there is the need to perform the same operations upon all of the Element objects, where the operation algorithms need to be different due to the differences in Element classes being operated upon.

  • where we can achieve code sharing or improved organisation of our program logic, by gathering together the code required for an operation that will be performed upon a diverse set of Element classes.

  • where we expect that we will be more likely to add further, or change existing, operations, than we will be to add further Element classes to be operated upon.

A Visitor may operate upon a individual Element objects, or it may operate upon a Composite collection of Element objects. The Visitor may accumulate information, pertaining to the collection as a whole, as it iterates through all of the member Elements. This is similar in function to an Internal Iterator (see Iterator pattern in the links below), however the Visitor pattern doesn't require that each of the Element objects that it will navigate through share a common base class or interface.

The Visitor pattern has a couple of potential problems:

  • we may be forced to compromise encapsulation, by needing to expose too much of the Element class's internals to make the Element classes "visitor ready"

  • it requires more source code changes if we need to add a new Element class where there are a lot of Visitor classes that will be required to operate upon it.

  • if overused it can increase undesirable coupling within our application, versus a solution where we just used polymorphism; ie. the Elements descend from an Abstract base class, and each Element overriding the operation" methods.

I have two illustrations of the Visitor pattern:

  • the first example has two Element classes, and two Visitor operations to act upon those Elements.

  • the second example shows a Visitor acting upon a composite object containing a mixed collection of Element objects. It operates upon the composite, and then provides statistics about the whole collection.

Here is the client code to run the first illustration:

        /* Construct two Element objects. They inherit from the same base
          class, but are of different types. Their shared base class is
          "visitor ready", and has a readonly Value property.
          Set their Value property by their differing mechanisms to
          the values "Borland" and "Switzerland". */
        ElementBase element = new ConcreteElement_1("Borland");
        ElementBase element2 = new ConcreteElement_2();
        ((ConcreteElement_2)element2).Name = "Switzerland";

        ShowUserCommentary(1);
        ShowContentsOfValueProperty(element.Value);  
        ShowContentsOfValueProperty(element2.Value);

        /* Create 2 Visitor objects. One can cause the target Element's
           Value property contents to be converted to upper case, and the
           other can cause the characters in the properties contents to
           become separated by the "_" character. */
        VisitorBase vCapitalise = new ConcreteVistor_1();
        VisitorBase vAddDashes = new ConcreteVistor_2();

        /* Apply the one Visitor to the 1st Element, and both Visitors the
           2nd Element. */
        element.Accept(vAddDashes);
        element2.Accept(vCapitalise);
        element2.Accept(vAddDashes);

        ShowUserCommentary(2);
        ShowContentsOfValueProperty(element.Value);
        ShowContentsOfValueProperty(element2.Value);

And this is the output:






The essential interface for the visitor pattern can be thought as as:

       // --- interfaces
        public interface IElementBase {
              void Accept(IVisitorbase v)
        }
        
        public interface IVisitorBase {
        }

The Visitor is passed into the Element's Accept method. The concrete Element class that receives the Accept method call will pass itself into the method within the Visitor object that specifically handles this flavour of Element concrete class as we are about to see. Here is the definition of the base class for the Element classes. The property is just something I need for the demonstration. The key thing is the Accept method, which is what is making the Element classes "visitor ready".

        // --- Element; the objects that get acted upon by the Visitors
        public abstract class ElementBase {
                // fields
                protected string _value;
                // properties
                public string Value {
                        get {return _value;}
                }
                // methods
                // ... method to make the Element visitor-ready
                abstract public void Accept(VisitorBase visitor);
        }

Next we shall look at the concrete Element implementations. The key part to focus upon is the overridden Accept methods. The incoming Visitor will have a separate method for each concrete Element class. The overridden Accept method calls the Visitor method that specifically handles this operation for this specific concrete Element class.

The other source code is just something to make the point that each of the concrete classes can have differing interfaces and mechanisms.

        public class ConcreteElement_1: ElementBase {
                // fields
                protected string _text;
                // properties
                public string Text {
                        get {return _text;}
                        set {
                                _text = value;
                                _value = value;
                        }
                }
                // constructor
                public ConcreteElement_1 (string aText) {
                this.Text = aText;
                }
                // methods
                override public void Accept(VisitorBase visitor) {
                        visitor.VisitElement_1(this);
                }
        }

        public class ConcreteElement_2: ElementBase {
                // fields
                private string _name;
                // properties
                public string Name {
                        get {return _name;}
                        set {
                                _name = value;
                                _value = value;
                        }
                } 
                // methods
                override public void Accept(VisitorBase visitor) {
                        visitor.VisitElement_2(this);
                }
        }

Next the definition of a base class for the Visitor classes. We have abstract method definitions for each concrete Element class so the compiler can check for us that each Visitor has been configured to handle all of the concrete Element classes.

        // --- Visitors; objects that will act upon upon the Elements
        public abstract class VisitorBase {
                // methods
                public abstract void VisitElement_1(ConcreteElement_1 element);
                public abstract void VisitElement_2(ConcreteElement_2 element);
        }

Finally we have the Concrete Visitors which do all of the work. As we can see the pattern relies up the fact that the Element classes have exposed enough of their own state to allow the Visitor to achieve it's objective. This exposure requirement can mean that the visitor pattern is unsuitable for our application. This could occur if we required so much exposure of the Element's internal state to the point where we felt that the Element class's encapsulation had been compromised.

        public class ConcreteVistor_1 : VisitorBase {
                // methods
                override public void VisitElement_1(ConcreteElement_1 element) {
                        element.Text = element.Text.ToUpper();
                }
                override public void VisitElement_2(ConcreteElement_2 element) {
                        element.Name = element.Name.ToUpper();
                }
        }

        public class ConcreteVistor_2 : VisitorBase {
                // methods
                override public void VisitElement_1(ConcreteElement_1 element) {
                        element.Text = FormatText(element.Text);

                }
                override public void VisitElement_2(ConcreteElement_2 element) { 
                        element.Name = FormatText(element.Name);
                }

                private string FormatText(string aText) {
                        StringBuilder retval = new StringBuilder();
                        char[] arr;
                        arr = aText.ToCharArray();
                        foreach (char ch in arr) {
                                retval.Append(ch);
                                retval.Append('_');
                        }
                        if (retval.Length > 0) retval.Remove(retval.Length-1,1);
                        return retval.ToString();
                }
        }

Visitor pattern – second illustration

In the first illustration we looked at a Visitor being applied to an individual object, this time we will look at the Visitor being dappled to a composite collection of diverse Element types. When our Visitor is acting upon a collection we have the option of accumulating state within the Visitor while it navigates through all the Elements in the collection as we will see in this example.

The collection itself is an implementation of the Composite pattern. This pattern is covered in my article upon the GOF's "Structural Patterns"; see link at the bottom of this article.

In my illustration the concrete Elements classes are various types of fruits. The collection is a fruit bowl that can contain a number of pieces of various types of fruit. Each piece of fruit has a designated weight. We have a "juice" operation that will convert the bowl of fruit into fruit juice. Each fruit type has an assumed percentage juice yield based upon the amount of juice to be expected from a piece of fruit of that type. The weight of juice that is expected from the fruit bowl is therefore determined by the fruit types, and the individual weights of the pieces of fruit.

Here is the snippet of client code, and the private method that it uses to display the results:

                     /* Try a different implementation. This time we have a
                        Composite class to contain a collection of Element 
                        classes. The Elements are fruit of various types 
                        and weights. */
                     FruitCollection fruitBowl = new FruitCollection();
                     fruitBowl.Add(new Apple(1.2f));
                     fruitBowl.Add(new Orange(1.4f));
                     fruitBowl.Add(new Apple(1.0f));

                     /* Create a Visitor. It converts the fruit to juice, and
                        calculates the accumulated juice yield (weight) for 
                        fruit objects that it operates upon. Differing fruit 
                        types may have differing yield percentages. The point 
                        is to show a visitor acting upon a collection, and
                        accumulating state during it's journey. */
                     ShowUserCommentary(3);
                     Juice juice = new Juice();

                     /* Apply the visitor to the collection; convert the fruit bowl
                        into juice. */.
                     fruitBowl.Accept(juice);

                     ShowJuiceStatistics(juice);
             /* Add another Element to the collection, reapply the Visitor
                to get a different result. */
             ShowUserCommentary(4);
             fruitBowl.Add(new Orange(0.8f));
             juice.Reset();
             fruitBowl.Accept(juice);

             ShowJuiceStatistics(juice);
     }

     private void ShowJuiceStatistics(Juice juiceVisitor) {
             listBox1.AppendText(String.Format(
                     "n Juice yield weight is {0:0.#}",
                     juiceVisitor.YieldWeight));

             listBox1.AppendText(String.Format(
                     "n Percentage apple juice = {0:0.#}",
                     juiceVisitor.PercentageApple));
     }

Here is the output:






Here is the implementation of the base class for the fruit Elements. The pattern doesn't require that our Element classes share a common base class, although I have one in this illustration. The pattern only requires that the Element classes implement an interface containing the Accept method.

        // --- Base class for the "Element" class in the pattern
        abstract public class FruitBase {
                // fields
                private float _weight;
                // properties
                public float Weight {
                get {return _weight;}
                }
                // constructor
                public FruitBase(float aWeight) {
                _weight = aWeight;
                }
                // methods
                // ... method to make the Element visitor-ready
                abstract public void Accept(Juice visitor);
                public void ResetWeight() {
                _weight = 0;
                }
        }

Next is the implementation of the Composite class for the bowl of fruit. As you can see it implements it's own "Accept" method, which iterates through the collection's member Elements, and calling the Accept method for each.

        // --- Collection of the "Element" objects
        public class FruitCollection {
                // fields
                private ArrayList _collection = new ArrayList();
                // methods
                public void Add(FruitBase aFruit) {
                        _collection.Add(aFruit);
                }   
                public void Remove(FruitBase aFruit) {
                        _collection.Remove(aFruit);
                }
                public void Accept(Juice visitor) {
                        foreach (FruitBase fruit in _collection) {
                                fruit.Accept(visitor);
                        }
                }
        }

Next the concrete Element classes:

        // --- Concrete "Element" classes
        public class Apple: FruitBase {
                // constructor
                public Apple(float aWeight) :base(aWeight) {
                }
                // methods
                override public void Accept(Juice visitor) {
                        visitor.VisitApple(this);
                }
        }

        public class Orange: FruitBase {
                // constructor
                public Orange(float aWeight) :base(aWeight) {
                }
                // methods
                override public void Accept(Juice visitor) {
                        visitor.VisitOrange(this);
                }
        }

Finally the implementation of the Visitor class. It contains the "juice" methods for each Element class type, and also the mechanisms for accumulating and returning state values.

     // --- Concrete "Visitor" class
     public class Juice {
             // fields
             protected float _weightApples, _weightOranges;
             // properties
             public float PercentageApple {
                     get {return 
                        (_weightApples * 100)/(_weightApples + _weightOranges) ;}
             }    
             public float YieldWeight {
                     get {return (_weightApples + _weightOranges) ;}
             }
             // methods
             public void VisitApple(Apple fruit) {
                     _weightApples += fruit.Weight * .85f;
             }
             public void VisitOrange(Orange fruit) {
                     _weightOranges += 
                          fruit.Weight * .75f;  // thick skin, less yield
             }
             public void Reset() {
                     _weightApples = 0;
                     _weightOranges = 0;
             }
     }

Conclusion

This article has continued examination of the Behavioural Patterns described by the GOF in their book titled "Design patterns". I think that the study of the design patterns is a worthwhile thing to do. I found the following links useful while studying the patterns myself and while preparing this article. The book itself is a good investment as it provides supplementary detail upon the problems that the patterns are trying to solve, the elements of the solution, and the consequences and trade-off's involved in using the patterns.

This completes my series of articles looking at the Design Patterns. I hope that you have found the articles helpful, and I wish you good luck with your system design adventures !

Links

  • Source code for this articles demonstration program The source and executable are stored at CodeCentral.

    • GOF Creational Patterns ... If you found this article helpful you may also enjoy my earlier article upon the Creational Patterns (Factory, Abstract Factory, Builder, Prototype and Singleton).

    • GOF Structural patterns ... I also have this article upon the Structural Patterns (Adapter, Bridge, Composite, Decorator, Facade, Flyweight & Proxy).

    • GOF Behavioural Patterns - part one: ... And this opening article upon the Behavioural Patterns (Chain of Responsibility, Command & Command).

    • GOF Behavioural Patterns - part two: ... And this following article upon the Behavioural Patterns (Iterator, Mediator, Observer & Memento).

    • GOF Book ... This link points to the GOF book on the publisher's web site.

    • http://www.ultrapico.com... Expresso – an excellent free ware tool for building and testing Regular Expressions (as used within the .Net Regex class).

    • UMLet ... "UMLet is an open-source lightweight Java tool for rapidly drawing UML diagrams with a sound and pop-up-free user interface. UMLet lets you draw diagram sketches fast; export diagrams to eps, pdf, jpg, svg, and system clipboard; share diagrams using Eclipse 3; and create your own custom graphical elements. " .... requires Sun Java 1.5

    • http://www.dofactory.com/Patterns/Patterns.aspx ... thumbnail sketches of all the design patterns with C# implementation examples

    • http://www.codeproject.com/csharp/#Design+and+Architecture ... contains a series of articles on the GOF patterns with C# implementation examples

Server Response from: SC3