Search  
Monday, September 06, 2010 ..:: Articles » GOF Creational Patterns with C# ::..   Login
 Creational Patterns
Introduction | Factory | Abstract factory | Builder | Prototype | Singleton | Links
 
Show as multiple pages

GOF Creational Design Patterns with C#

By Barry Mossman from Primos.com.au

The GOF design patterns help address the following challenges :

    • design ready to accommodate change & growth

    • design flexible systems which 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 from 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.

This article is the first in a series. It discusses why and when you would want to use the design patterns, and demonstrates a C# implementation of the patterns. There is source code for my demonstration program available (see links section). The program contains annotated example displays. It also displays some brief notes about the patterns, so if you are interested in starting to work with the patterns it may be a useful utility to have on your desktop during the learning period.

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 and levity. The subtitle of the book is "elements of reusable object-oriented software". If you are not familiar with the book you have probably seen it in a bookshop somewhere.

The GOF described various categories of patterns:

  • Creational Patterns <=== discussed in this article

  • Structural Patterns

  • Behavioral Patterns

The Creational Patterns are:

  • Factory

  • Abstract Factory

  • Builder

  • Prototype

  • Singleton

General techniques promoted by the GOF

  1. Decouple our client code from the classes of the objects that it uses:

    Why ?

  • Code our client to use like classes generically, so that we reduce the need for switch blocks.

  • Anticipate the virtually certainty that in the future it will become necessary to change the implementation of the classes that our client uses.

  • When this happens maybe:

    • we need to leave the old version 1 class in place as other clients are still using it (a requirement to ensure absolute backwards compatibility is a task that is nice to avoid)

    • our new enhanced system is going to be more flexible, and the actual class which is to be instantiated by our client can now vary at runtime. Perhaps we now have have several subclasses inheriting from the version 1 class, and runtime conditions will determine which of the subclasses that we will need to instantiate.

    • our new release introduces some form of object pooling so that the client is no longer causing the creation of new object for each individual use.

  • The aim is to write our client in such a manner that these kind of changes can occur to the objects that it uses, without forcing code changes within the client itself.

  • The general technique is to outsource object creation to one of these Creational Design Patterns, and then to reference the objects created via a base class rather than addressing them explicitly via their concrete class types.

  1. Favour "object composition" over "class inheritance"

  • in "class inheritance":

    • the issue of code reuse is addressed by breaking our business objects down to generic classes where possible, and then to build up the classes we actually use via class inheritance.

    • has the advantages that this supported by the programming language, is simple to use, and the resulting application architecture is easy to understand

    • has the disadvantages that

      • can lead to an implementation where the parent classes have too much bearing on the subclass's implementation. Encapsulation becomes compromised as the subclasses can have too much knowledge of their parent's implementation. Change at either level is liable to require change at the other level. Reuse of a subclass for a future extension is more likely to require change at the parent level also.

      • hampers runtime flexibility where we would able to change the behaviours being inherited, as this has been decided at compile time.

      • reuse is only available at the whole logical object level, rather than at the level of just one of the behaviours of the logical object

  • "object composition"

    • here the business objects which our client will use are assembled from a number of helper classes working together to assemble the behaviour required which would have been delivered by the class inheritance model used in the class inheritance technique.

    • has the advantages that:

      • our objects can be more flexible because their behaviour can be assembled dynamically at runtime, rather than fixed at compile time through inheritance

      • we are less likely to allow our classes grow into an unmanageable size

      • we are likely to get good levels of reuse, and reduced levels of rework.

    • but has the disadvantage that our system design can be harder to understand as it's operation is delivered via the inter-relationships between the helper classes rather than from just a few business classes

      • the Design Patterns themselves provide a language with which we can describe and document the system design to help overcome this disadvantage

    • 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

  1. Algorithms that are likely to change should be isolated into a to reduce the impact when this happens.

      • There are various patterns which are designed to isolate such algorithms away into a helper class on their own which is a design technique that is ready for change and likely to minimise impact upon other sections of our code.

The Creational Patterns have an important part to play in the deployment of these techniques that the GOF are advocating

    • the Creational Patterns provide the structures to achieve the objective of decoupling our client from the classes which it uses

    • the Creational Patterns are not involved in the object composition approach to system design, but this approach will result in our application having an increased quantity of physical classes. The success of the strategy when faced with future growth or change, depends upon decoupling, which makes the Creational Patterns crucial.

    • The logic involved in the instantiation and initialisation of the classes that we deploy will be a likely area for future change. This makes these algorithms likely candidates for isolation, and the Creational Patterns are those which achieve this objective.

A summary of the patterns

Pattern Name

General objective

Factory

Most basic creational pattern.

Can be used on it's own, or used within the patterns following.

Delivers all the basic objectives mentioned above.

Abstract Factory

Allows us to group the objects that we want to use into families.

Our client can then decide which family it wants to use based upon some configuration or runtime option.

The Abstract Factory will instantiate objects from just the chosen family.

Our client will operate with objects from the chosen family using generic calls that would work with any other family.

Prototype

We first build and configure a prototype, maybe using one of the other patterns.

Our client can then clone from the prototype to create instances as it requires them.

Our client can operate, with generic code, upon either the prototype, or upon any of the clones.

Facilitates runtime flexibility as we can control how the prototype is configured at runtime, and then our client can create cloned instances as required as if this was a class that was defined into the system at compile time.

Builder

The building of our object is outsourced to two helper classes.

One class controls what is built, and the other controls how it is built.

This means that we can have features and options with the classes that we use, as well as decoupling our client from the physical classes that it is uses.

The mechanics of the features and options assembly is outsourced from our client.

Singleton

This is a specialist pattern that gives the client access to an object that is created with only the one instance, and is shared across the application.

The pattern relieves the client of the responsibility of ensuring that there is just the one instance regardless of how many attempts are made to instantiate the object.


Factory Pattern

To illustrate the benefits of the Factory pattern my demonstration client program uses an object that provides a public SayWho behaviour, which returns a string showing the object's name. Here is an example of it's use:

listBox1.AppendText(Product.SayWho());

The aim is to allow the client to instantiate and use this object in a manner that is accepting of change. The object will become the product of a “factory”. If there are various flavours of product we want to write reuable generic client code rather than have untidy switch blocks everywhere. We want to be able to provide a new implementation of the initial "product" class's behaviour, and have the same client still able to run without change, now using the new product class.

We also wish to protect our client from any complexities or background work that may be involved in creating an instance of our object.

To achieve this first we define a base class for our "product" classes.

        // --- Abstract product
        abstract public class ProductBase {
                public string SayWho() {
                        return "\n   * " + this.ToString();
                }
        }

We then create a factory class to instantiate "product" objects. This is done so that the instantiation of the "product" class is outsourced, away from our client, meaning that our client no longer need know the class name of the object which it is using. In this example I have passed a parameter into the factory's MakeProduct method so that the factory could be later changed to be more flexible about the flavour of product that it instantiates.

        // --- Abstract factory
        public abstract class   FactoryBase {
                abstract public ProductBase     MakeProduct(int t);
        }

        // --- Concrete factories
        public class ConcreteFactory_A: FactoryBase {
                public override ProductBase     MakeProduct(int t) {
                        return new ConcreteProduct_A();
                }
        }

We can now code our client as follows. Note that the "product" variable is defined using the abstract base class. rather than the concrete class which will be instantiated. We will be able to change the class of product that the client is using by issuing a new version of the ConcreteFactory class which returns a different class of product. As long as the new product implements the same signature as the old product our client will not notice the difference.

        FactoryBase Fact = new ConcreteFactory_A();
        ProductBase Product = Fact.MakeProduct(0);
        listBox1.AppendText(Product.SayWho());

To get a little leverage out of the factory pattern we need to need to define a new generation, but similar product class. We will create a “B” factory to make the new generation B-type objects. This factory can make two types of object, one extends the original interface, so that it now also provides a SayWhen behaviour. Firstly we should look at the concrete implementation of the products.

   // --- Interface for extended product

   public interface IExtendedProduct 
   {
                    string SayWhen();
   }

   // --- Concrete products

   public class ConcreteProduct_A: ProductBase {}

   public class ConcreteProduct_B_1: ProductBase {}

   public class ConcreteProduct_B_2: ProductBase, IExtendedProduct 
   {
           public string SayWhen() 
           {
                return (String.Format("\n   * {0:f}",System.DateTime.Now));
           }
   }

Then the new factory.

   public class ConcreteFactory_B: FactoryBase {
       override public ProductBase     MakeProduct(int t) {
           switch (t) {
               case 1:
                  return new ConcreteProduct_B_1();
               case 2:
                  return new ConcreteProduct_B_2();
               default:
                  throw new Exception("Invalid product request");
           }
       }
   }

The client can use the new products with an unchanged "Product.SayWho()" call. It can also be coded to recognise the products with the extended behaviour, and use this behaviour when appropriate.

  Fact = new ConcreteFactory_B();
  Product = Fact.MakeProduct(1);
  listBox1.AppendText(Product.SayWho());
  if (Product is IExtendedProduct)
     listBox1.AppendText(((IExtendedProduct)Product).SayWhen());}

If version 2 of our application requires modification to a product class we can produce a new factory to produce the new version objects. Another approach is to descend from the version 1 factory, and handle any new version products from the descendant, while letting the version 1 factory continue to produce an heritage products.

    public class ConcreteFactory_B_V2: ConcreteFactory_B {
        override public ProductBase     MakeProduct(int t) {
            switch (t) {
                case 3:
                    return new ConcreteProduct_B_1_V2();
                default:
                    return base.MakeProduct(t);
            }
        }
    }

Here is the output from our client demonstrating the above points:


And here is a diagram showing the pattern's particants and interactions:


We can introduce some runtime flexibility by using Reflection along with the factory pattern. I will introduce an xml runtime configuration file with the following contents.

<Factories>
        <Factory name="ConcreteFactory_C">
                <Products>
                        <Product name="1" class="Factory.ConcreteProduct_C">                            
                        </Product>
                </Products>
        </Factory>
</Factories> 

I will call this file “RuntimeConfig.xml”. My factory can then parse this file to obtain the qualified name (class and namespace name) of the concrete product that it will create for the client.

/* Here we increase runtime flexibility by using a runtime 
 * configuration file to control which concrete class is 
 * produced by our factory. */
public class ConcreteFactory_C: FactoryBase {
    override public ProductBase     MakeProduct(int t) {
        const string xmlDoc = @"RuntimeConfig.xml";
        string factoryName = "ConcreteFactory_C";

        // Load the runtime configuration file
        XmlDocument document = new XmlDocument();
        try {
            XmlTextReader reader = new XmlTextReader(
                 new FileStream(xmlDoc, FileMode.Open));
            reader.WhitespaceHandling = WhitespaceHandling.None;
            document.Load(reader);
            reader.Close();
        } 
        catch (FileNotFoundException ex) {
            throw new ApplicationException
                      ("Runtime config file named " 
                       + xmlDoc + " needed.", ex);
        } 
        catch (XmlException ex) {
            throw new ApplicationException(
               String.Format
                     ("Config file named {0} is poorly formed; {1}"
                     ,xmlDoc, ex.Message), ex);
        }

                                     
        /* Obtain the class name for the product that the 
         * caller has requested. */
        string search = String.Format(
            @"Factories/Factory[@name='{0}']/Products/Product[@name='{1}']",
            factoryName, t);
        string className = "";
        try {
            XmlNodeReader nodeReader  
                = new XmlNodeReader(document.SelectSingleNode(search));                               
            nodeReader.MoveToContent();
            className = nodeReader.GetAttribute("class");
            if (className == "")
                throw new ApplicationException(String.Format(
                    "Class name is blank in config file {0} for product {1} for factory {2}",
                     xmlDoc,t,factoryName,t));
        } 
        catch (NullReferenceException) {
            throw new ApplicationException(String.Format(
                "No classname for product {0} in file {1} for factory {2}",
                 t,xmlDoc,factoryName));
        }

Our factory then uses Reflection as follows to create an instance of class that was named in the config file:

     Assembly assem = Assembly.GetExecutingAssembly();
     Type productType = assem.GetType(className);
     if (productType == null)
         throw new ApplicationException(String.Format("Cannot find class {0} 
mentioned in config file {1} for factory {2}, product {3}"
, className,xmlDoc,factoryName,t)); return (ProductBase)Activator.CreateInstance(productType);

Abstract Factory Pattern

The Factory pattern allowed us to decouple our client from an object which it uses. The Abstract Factory pattern extends this idea to manage separate families of objects.

A runtime selection, or configuration option, in our client could decide which family of objects is to be used. The Abstract Factory pattern allows us to write generic code to instantiate and use the family objects regardless of which family is chosen at runtime. The pattern also helps us enforce a rule where objects from just the chosen family are used uniformly by the client.

The classes in my demonstration program's "family" each provide the public SayWho, and sometimes the SayWhen methods as in the Factory pattern example. This similarity of function is just to simplify the example. The "product" classes within the family do not need to bear any similarity, it just that each family should a similar structure, ie. same number of classes, and when looking across the families, each equivalent class should have the same public signature.

 /* -----------------------------
 The products within a single family do not need to descent from
 a common ancestor but we need to ensure that across families 
the various products have the same interface.

    FamilyA    FamilyB
    -------    -------
    Product1   Product1  <-- These should have a common interface.
    Product2   Product2  <-- These may be different to those above,
                             but they need to be the same as each other.
    Product3   Product3  <-- etc
 ------------------------------------------ */

The Product classes need the same interface, but need not descent from a common base class. I will connect them together via interface definitions so that the client can recognise the grouping, and so that the compiler will ensure that I have implemented them uniformly.

Use of the Abstract Factory pattern means that generic code such as the following client code can be used upon an object family.

   private void AbstractFactory_CreateAndUseFamilyProducts(FactoryBase AF) {
       /* Either family A or family B products are created dependant upon
       the concrete factory that was passed in via the AF paramter*/
       IProduct1 AP1 = AF.CreateProduct1();
       IProduct2 AP2 = AF.CreateProduct2();
       IProduct3 AP3 = AF.CreateProduct3();
       // use family members generically
       AbstractFactory_UseProductsGenerically(AP1);
       AbstractFactory_UseProductsGenerically(AP2);
       // or use a specific family member
       listBox1.AppendText(AP3.SayWho());
   }

   private void AbstractFactory_UseProductsGenerically(IProductBase AP) {
       listBox1.AppendText(AP.SayWho());
        if (AP is IProduct2)
                 listBox1.AppendText(((IProduct2)AP).SayWhen());
   }

The client can use products from either family without change.

   FactoryBase AF = new ConcreteFactory_A();

   // Use family A products
   ShowUserCommentary(1);   // display explanatory notes on the UI
   AbstractFactory_CreateAndUseFamilyProducts(AF);

   // or have the same code create and use family B products
   ShowUserCommentary(2);
   AF = new ConcreteFactory_B();
   AbstractFactory_CreateAndUseFamilyProducts(AF);

The above causes my demonstration program to display:




To implement the Abstract Factory we firstly define interfaces for our family set:

   public interface IProductBase {         // optional
        string SayWho();
   }

   public interface IProduct1: IProductBase {}

   public interface IProduct2: IProductBase {
         string SayWhen();
   }

Then our concrete products:

   // --- Concrete products
   public class ConcreteProduct_A_1: ProductBase, IProduct1 {
   }

   public class ConcreteProduct_A_2: ProductBase, IProduct2 {
       public string SayWhen() {
           return (String.Format("\n   * {0:f}",System.DateTime.Now));
       }
   }

   public class ConcreteProduct_A_3: ProductBase, IProduct3 {}

   public class ConcreteProduct_B_1: ProductBase, IProduct1 {}

   public class ConcreteProduct_B_2: ProductBase, IProduct2 {
       public string SayWhen() {
           return (String.Format("\n   * {0:f}",System.DateTime.Now));
       }
   }
   public class ConcreteProduct_B_3: ProductBase, IProduct3 {}

We then define the base class for our Abstract Factories:

   // --- Abstract Factory
   abstract public class FactoryBase {
           abstract public IProduct1 CreateProduct1();
           abstract public IProduct2 CreateProduct2();
           abstract public IProduct3 CreateProduct3();
   }

Finally the concrete classes for the abstract factories:

   // --- Concrete factories
   public class ConcreteFactory_A: FactoryBase {
       public override IProduct1 CreateProduct1() {
           return new ConcreteProduct_A_1();
       }
       public override IProduct2 CreateProduct2() {
           return new ConcreteProduct_A_2();
       }
       public override IProduct3 CreateProduct3() {
           return new ConcreteProduct_A_3();
       }
   }

   public class ConcreteFactory_B: FactoryBase {
       public override IProduct1 CreateProduct1() {
           return new ConcreteProduct_B_1();
       }
       public override IProduct2 CreateProduct2() {
            return new ConcreteProduct_B_2();
       }
       public override IProduct3 CreateProduct3() {
            return new ConcreteProduct_B_3();
       }
   }

Builder Pattern

The Builder pattern becomes useful where our client uses objects that are more complex to construct than just a simple "= new YourClass()". This pattern uses two entities which collaborate to build the target class;

  • the Builder which determines what gets built

  • and the Director which determines how it gets built

This creational pattern facilitates a system design where the objects that we use could be considered to have features and options that are dynamically chosen at run time.

Also the "object" built by the Builder could be more complex than just the instantiation of just a single class. The builder could for example built an instance of the main object, then build several associated or child objects that the main object will contain references to. Our client will be shielded from this complexity. From it's perspective it is just asks for, and gets returned, a simple object instance.

In my example the object my client is to use has the now familiar SayWho method.

I have two Builders:

  • one creates an object whose SayWho behaviour is to issue a greeting and state the class name of it's builder

  • the other object does as above, then also states it's creation time

I have two Directors:

  • one assembles a terse version of the object to be instantiated

  • the other assembles are more chatty version

The client therefore has the flexibility of being able to build either object, and then to have that object built in either style. It does that by choosing which Builder and which Director to use to create the object. The client is shielded from which actual class is built and how it is constructed, as it's generic use of the object will work with whichever class is actually built.

Here is the output from my demonstration program.

Here is the client code that produces the above output.

The client is shielded from knowing which class of object is actually created, and is also shielded from knowing how the object is configured.

    // Create a Builder & a Director
    director = new DirectorTerse();
    builder = new BuildUntimedGreeting();

    // Now use these to create an object, and then use that object.
    BuildAndUseObject(director, builder);

    ShowUserCommentary(2);

    // Create another Director. Use it with the previous Builder, 
    // using the same generic client code, to create the same 
    // type of object but with different behaviour due to 
    // different creation options taken by the new Director.
    director = new DirectorChatty();
    BuildAndUseObject(director, builder);

    ShowUserCommentary(3);

    // Create a new Builder which builds a new generation object.
    // Create the object using the 1st Director. So we have 
    // the same creational/setup instructions from the 
    // Director & the same client code, but we get different 
    // behaviour when using the object with the same generic 
    // client code.
    builder = new BuildTimedGreeting();
    director = new DirectorTerse();
    BuildAndUseObject(director, builder);

    ShowUserCommentary(4);

    // Same story with the new Builder with the second Director.
    director = new DirectorChatty();
    BuildAndUseObject(director, builder);
}

    /* Generic code to create and use the object */ 
    private void BuildAndUseObject(DirectorBase director, BuilderBase builder) {
            ProductBase product;
            director.Construct(builder);
            product = builder.GetResult();
            listBox1.AppendText(product.SayWho());
    }

Firstly we will look at the Builders which determine which object is to be built and returned to the client. The configuration of the object to be built (in my case the _message, _owner & _timestampFormat variables) will be set up by the Director). The only section that is relates to the Builder pattern is the GetResult method which returns the constructed object to the client. The remainder are just part of the functionality of my demonstration program.

  // --- Abstract Builder
  abstract public class BuilderBase {
     // fields
     protected string _message;
     protected string _owner;
     // methods
     public void BuildMessage(string text) {
             _message = text;
     }
     public void BuildOwner(string owner) {
             _owner = owner;
     }
     virtual public void BuildTimeStampFormat(string timestampFormat) {}
     abstract public ProductBase GetResult();
 }

 // --- Concrete Builders
 public class BuildUntimedGreeting: BuilderBase {
     override public ProductBase GetResult() {
            return new UntimedGreeting(_message,_owner);
     }
 }

 public class BuildTimedGreeting: BuilderBase {
     // fields
     private string _timestampFormat;
     // methods
     override public ProductBase GetResult() {
         return new TimedGreeting(_message,_owner,_timestampFormat);
     }
     override public void BuildTimeStampFormat(string timestampFormat) {
         _timestampFormat = timestampFormat;
     }
 }

Then we have the Directors which control how the Builder constructs the object to be built.

 // --- Abstract Director
 public abstract class DirectorBase {
     abstract public void Construct(BuilderBase builder);
 }

 // --- Concrete Directors
 public class DirectorTerse: DirectorBase {
     // methods
     override public void Construct(BuilderBase builder) {
         builder.BuildMessage("Hi");
         builder.BuildOwner(this.ToString());
         builder.BuildTimeStampFormat("t");
     }
 }

 public class DirectorChatty: DirectorBase {
     // methods
     override public void Construct(BuilderBase builder) {
         builder.BuildMessage("Hello it is wonderful to see you.");
         builder.BuildOwner(this.ToString());
         builder.BuildTimeStampFormat("F");
     }
 }

Finally for completion here is the implementation of one of the objects that will be created by my demonstration of the Builder pattern.

 // --- Abstract Product
 abstract public class ProductBase {
         abstract public string SayWho();
 }

 // --- Concrete products
 public class UntimedGreeting: ProductBase {
        // fields
        private string _text;
        private string _owner;
        // constructer
        public UntimedGreeting(string input, string owner) {
              _text = input;
              _owner = owner;
         }
        // methods
        override public string SayWho() {
              return String.Format("   * {0}\n   * I was build by {1}\n",
                       _text,_owner);
        }
 }






Prototype Pattern

The Prototype Pattern approaches the creation of the objects that our client will use by cloning instances from prototypes as required. This achieves the general aim of decoupling the client from the objects that it will use, but also adds some advantages unique to the Prototype pattern.

  • Enhanced run time flexibility

      Prototypes can be created dynamically by our client. For example our client can create an instance of one of our classes (let us call it type AnyType). It can set of few properties on this instance, and then make it available as a prototype. It can create a second instance of type AnyType setting the properties differently. This can now be a second prototype. Our client can then clone instances of either prototype as it needs objects to work with, as if it were instantiating different classes hard defined at runtime. We have the runtime flexibility of being able to decide how many prototypes are created, and how they are to be configured. This allows our clients to easily configure themselves to their runtime or environmental conditions.

  • May simplify system design

      The Prototype Pattern may enable us to design our system with a smaller number of classes, or enable us to use less sub classing. Consider a system where we would have defined a generic class, and then a number of inherited subclasses to provide similar, but subtly different, behaviours. In this case we may be able to design the system with just one class, where the different flavours are achieved by instantiating and tailoring, at runtime, a number of prototypes from the one generic class.

The example program uses a single class to build prototypes from. This class has the SayWhen behaviour from earlier examples. The prototypes are set up to show the datetime in differing formats. Clones are then created. The clones are altered by having the time print in lower case, so that we can see that each clone is a separate instance from the prototype from which it was made.

Here is the client code which creates and uses the above instances of prototypes and clones. This could be further improved by using the Factory Pattern to create the prototypes, in this way the client code will not be aware of the class being used. I have not done this so that we can focus upon just the Prototype pattern.

   /* In this example a method in the generic object states 
   it's type and gives the date. The various "sub-types" use 
   differing time formats.The property ynShout controls 
   whether the time is converted to uppercase. The intent is 
   to show that we can use the prototype pattern to create 
   differing flavours of our class by varying the prototype. */

   // create a product; state time using DateTime format "y"
   ProductBase pr = new ConcreteProduct("y");
   // now use Prototype pattern capability to clone a copy
   ProductBase clone = pr.Clone();
   // change original so can be seen to be seperate instance from 
   // the clone
   pr.Shout = true;

   // create, and clone,  a different flavour product; format "f"
   ProductBase pr2 = new ConcreteProduct("f");
   ProductBase clone2 = pr2.Clone();
   pr2.Shout = true;

   // use either the original, or the clone, using generic code
   ShowUserCommentary(1);
   UseProduct(pr);

   ShowUserCommentary(2);
   UseProduct(clone);
                                                  
   ShowUserCommentary(3);
   UseProduct(pr2);
   UseProduct(clone2);
}

private void UseProduct(ProductBase product) {
        listBox1.AppendText(product.SayWhen());
}  

Here is the implementation of the class that our client is using to build the prototypes from. Focus upon the Clone method, as the other code just relates to my demonstration example rather that the Prototype pattern itself. Note that the .NET framework makes it easy for us to implement a basic form of cloning via the Memberwise Clone method.

// --- Abstract Product
public abstract class ProductBase {
    // fields
    protected string _whenFormat;
    private Boolean _shout = false;

    // properties
    public string WhenFormat {
        get {
            return _whenFormat;
        }
        set {
            _whenFormat = "{0:" + value + "}";
        }
    }
    public Boolean Shout {
        get {
            return _shout;
        }
        set {
            _shout = value;
        }
    }

    // constructors
    public ProductBase( string ID ) {
        WhenFormat = ID;
    }

    // methods
    public abstract string SayWhen();

    public ProductBase Clone() {
        // Shallow copy
        return (ProductBase)this.MemberwiseClone();
    }

}

// --- Concrete products

public class ConcreteProduct: ProductBase {
    // constructors
    public ConcreteProduct(string ID) : base (ID) {}

    // methods
    override public string SayWhen() {
        string _st1 = "\n   * " + this.ToString()+ ": ";
        string _st2 =  String.Format(this._whenFormat,System.DateTime.Now);
        string _st2a = this.Shout ? _st2.ToUpper() : _st2;
        return(_st1 + _st2a);
    }
}

I said above that the MemberwiseClone method provides a basic version of cloning. This is because MemberwiseClone provides just a shallow copy of the prototype. This means that if our prototype contained references to associated or child objects, the clone created will share the same associates or children that the prototype used. If we were wanting to clone a whole new structure our clone method would need to call MemberwiseClone for each of the object that the prototype refers to.


Singleton Pattern


The Singleton pattern is a specialist creational pattern as it's primary focus is to facilitate a single shared instance of our object rather than to decouple our client from the object's implementation as with the other creational patterns.

The pattern is useful when our design requires an object for which there must be only one instance that will be shared throughout the application. The point of the pattern is relieve the client of the task of ensuring that there is only one instance of this object. This will simplify the client by allowing it to focus upon the business intent rather than a mechanics issue. It will also avoid a potential client program bug where one reference to the object incorrectly allows another instance to be created. The following shows the client "creating" and using the singleton object.

  ShowUserCommentary(1);
  // call for a singleton instance. Since this is the first 
  // call this will trigger the creation of the instance.
  SingletonObject product1 = SingletonObject.Instance;
  // use the instance
  listBox1.AppendText(product1.SayWho());

  ShowUserCommentary(2);
  // call for a singleton instance again. We will get given 
  // the same instance
  SingletonObject product2 = SingletonObject.Instance;
  listBox1.AppendText(product2.SayWho());

This produces the following output from my demonstration program which shows the same singleton instance has been attached to both IProduct variables..

An implementation of the Singleton pattern typically involves the use of static variables, with the addition of synchronization if you want to be thread safe in a situation where it is possible that two threads will both make their initial access to the singleton at the same time. Here is a simpler thread safe implementation based upon ideas in an MSDN article I saw by Mark Townsend of Microsoft (see link at the end of this article). The instantiation of the SingletonObject class is triggered by the first reference to it's static Instance property. Since the SingletonObject 's class's constructor is not static, the static Instance property is initialised after the initialisation of the class which allows us to have the property return an instance of the class that contains it.

   // concrete Singleton
   public class SingletonObject {
       // fields
       private static readonly SingletonObject singletonObjectInstance = new SingletonObject();
       long _countUse = 1;
       // properties
       public static SingletonObject Instance {
              get {
                      return singletonObjectInstance;
              }
       }
       // constructor
       private SingletonObject() {}  // private, so cannot 
                                     // be used by a client

       // methods
       public string SayWho() {
              return String.Format("   * {0}: used {1} times\n",this.ToString(),_countUse++);
       }
   }

This implementation of the pattern is runtime efficient as we get a lazy load, meaning that the singleton object is only instantiated if our client actually executes a line of code which uses it's “Instance” property. However this lazy load feature is only assured if our Singleton class has no static members additional to the “Instance” property shown above. If we introduce additional static members we may think that they are available for use without triggering the overhead involved in the creation of an object, however this is not the case. Any use of a static member within a class will trigger the initialisation of all of the classes other static members, and in this case it will include the initialisation of our “Instance” property, which will in turn create the object even if the client session does not run through any code that will require the object.

There is a link at the bottom of this article pointing to an interesting technique, written by “davojc”, where he obtains singleton functionality via a .generic singleton provider implemented with .Net v2's Generics capability. This would allow us to have a class (eg. SomeNormalClass) offering the SayWho behaviour which would operate in a non-singleton manner, but if we accessed it as follows then we would get the singleton behaviour. This technique also avoids having to put the static field and property into each of our Singleton classes.

SingletonObject product1 = GenericSingletonProvider<SomeNormalClass>.Instance;

Here is my client demonstrating this option.

   ShowUserCommentary(3);
   /* Create a non-singleton object and use it. Repeat, and see 
    * that we have created a fresh object */
   SomeNormalClass product3 =  new SomeNormalClass();
   listBox1.AppendText(product3.SayWho());
   SomeNormalClass product4 = new SomeNormalClass();
   listBox1.AppendText(product4.SayWho());

   ShowUserCommentary(4);
   /* Now go through the same steps via a SingletonProvider 
   /* and see that we get, and reuse, just the one instance.*/
   SomeNormalClass product5 = 
         SingletonProvider<SomeNormalClass>.Instance;
   listBox1.AppendText(product5.SayWho());
   SomeNormalClass product6 = 
         SingletonProvider<SomeNormalClass>.Instance;
   listBox1.AppendText(product6.SayWho());






I won't repeat the implementation code here, but it is available from “davojc”s article, which can be accessed via my the links section at the bottom of this article, and it is also included in my demonstration program which is also available via my links section.


Conclusion

This article has examined the Creational set of patterns from those described by the GOF in their book titled "Design patterns". I found that study of their design patterns was a worthwhile thing to do. The following links were helpful 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-offs involved in using the patterns.

The source for demonstration program that has been refered to throughout this article is also avalable for download. It includes a “notes” facility where it displays some brief background for each of the patterns, so if you decide to start using the patterns this program may be useful to you while you are in learning mode. The following diagram shows the factory pattern in both “demonstration” and “notes” modes.




In my next article I look at the GOF's Structural Patterns.

Links


      

Copyright 2005 by Primos Computer Services   Terms Of Use  Privacy Statement