C# Design Pattern Essentials (2012)

Part II. Creational Patterns

This part describes the five creational patterns, that is, those that help manage the instantiation of objects.

·               Abstract Factory: Provide an interface for creating families of related or dependent objects without specifying their concrete classes;

·               Builder: Separate the construction of a complex object from its representation so that the same construction process can create different representations;

·               Factory Method: Define an interface for creating an object, but let subclasses decide which class to instantiate;

·               Prototype: Specify the kinds of objects to create using a prototypical instance, and create new objects by copying the prototype;

·               Singleton: Ensure a class allows only one object to be created, providing a single point of access to it.

2. Abstract Factory

Type: Creational

Purpose: Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

The Foobar Motor Company makes cars and vans, which when being built comprises (among lots of other things) a body shell, a chassis and glassware for the windows. Although both cars and vans need all of the same types of components, the specifics of each type differ depending upon whether it is being used for a car or a van.

In other words:

·               A car's body shell is different from a van's body shell;

·               A car's chassis is different from a van's chassis;

·               A car's glassware is different from a van's glassware.

Therefore, when we need to build a vehicle we can think of the components as coming from different 'families'; that is, when we build a car we use one family of components and when we build a van we use a different family of components.

We can thus model the components into simple hierarchies, as illustrated in the following figure:

Figure 2.1 : IBody, IChassis & IGlassware class hierarchies

As you can see, there is an interface for IBody having implementations of CarBody and VanBody. Likewise we have similar separate hierarchies for IChassis and IGlassware.

The code for the IBody hierarchy is very simple:

public interface IBody
{
    string BodyParts { get; }
}

public class CarBody : IBody
{
    public virtual string BodyParts
    {
        get
        {
            return "Body shell parts for a car";
        }
    }

}

public class VanBody : IBody
{
    public virtual string BodyParts
    {
        get
        {
            return "Body shell parts for a van";
        }
    }

}

The code for the IChassis hierarchy is almost identical:

public interface IChassis
{
    string ChassisParts { get; }
}

public class CarChassis : IChassis
{
    public virtual string ChassisParts
    {
        get
        {
            return "Chassis parts for a car";
        }
    }

}

public class VanChassis : IChassis
{
    public virtual string ChassisParts
    {
        get
        {
            return "Chassis parts for a van";
        }
    }

}

And likewise the code for the IGlassware hierarchy:

public interface IGlassware
{
    string GlasswareParts { get; }
}

public class CarGlassware : IGlassware
{
    public virtual string GlasswareParts
    {
        get
        {
            return "Window glassware for a car";
        }
    }

}

public class VanGlassware : IGlassware
{
    public virtual string GlasswareParts
    {
        get
        {
            return "Window glassware for a car";
        }
    }

}

Now we need a way of getting the correct family of parts (either for a car or for a van) but without having to explicitly instantiate the specific type in client programs each time we require them. To accomplish this, we shall define "factory" classes that will do this for us:

Figure 2.2 : Abstract Factory pattern

The AbstractVehicleFactory class is an abstract class that defines the abstract methods CreateBody(), CreateChassis() and CreateGlassware(), returning an IBody, IChassis and IGlassware object respectively:

public abstract class AbstractVehicleFactory
{
    public abstract IBody CreateBody();
    public abstract IChassis CreateChassis();
    public abstract IGlassware CreateGlassware();
}

The concrete subclass CarFactory returns the objects specific for the car family:

public class CarFactory : AbstractVehicleFactory
{
    public override IBody CreateBody()
    {
        return new CarBody();
    }

    public override IChassis CreateChassis()
    {
        return new CarChassis();
    }

    public override IGlassware CreateGlassware()
    {
        return new CarGlassware();
    }
}

The concrete subclass VanFactory returns the objects specific for the van family:

public class VanFactory : AbstractVehicleFactory
{
    public override IBody CreateBody()
    {
        return new VanBody();
    }

    public override IChassis CreateChassis()
    {
        return new VanChassis();
    }

    public override IGlassware CreateGlassware()
    {
        return new VanGlassware();
    }
}

Now it just remains for client programs to instantiate the appropriate 'factory' after which it can obtain the correct parts without having to specify whether they are for a car or a van:

Figure 2.3 : How clients use Abstract Factory

string whatToMake = "car"; // or "van"

AbstractVehicleFactory factory = null;

// Create the correct 'factory'...
if (whatToMake.Equals("car"))
{
    factory = new CarFactory();
}
else
{
    factory = new VanFactory();
}
 

// Create the vehicle's component parts...
// These will either be all car parts or all van parts
IBody vehicleBody = factory.CreateBody();
IChassis vehicleChassis = factory.CreateChassis();
IGlassware vehicleGlassware = factory.CreateGlassware();

// Show what we've created...
Console.WriteLine(vehicleBody.BodyParts);
Console.WriteLine(vehicleChassis.ChassisParts);
Console.WriteLine(vehicleGlassware.GlasswareParts);
Console.Read();

Therefore your client program needs to know if it is making a car or a van, but once it has instantiated the correct factory all the methods to create the parts can be done using an identical set of method calls.

The main disadvantage of the Abstract Factory pattern arises if you need to add additional 'products'. For example, if we now need to include lights in the family of components, we would need to amend AbstractVehicleFactory, CarFactory and VanFactory, in addition to creating a new ILights hierarchy (CarLights and VanLights).

3. Builder

Type: Creational

Purpose: Separate the construction of a complex object from its representation so that the same construction process can create different representations.

The Foobar Motor Company makes cars and vans, and the construction process of each differs in detail; for example, the body shell of a van comprises a cab area and a large reinforced storage area, whereas a saloon car comprises a passenger area and a luggage area (i.e. boot). And of course there a number of complex steps that have to be undertaken regardless of what type of vehicle is being built.

The Builder pattern facilitates the construction of complex objects by separating the individual steps into separate methods in a Builder hierarchy, and then using a Director object to specify the required steps in the correct order. Finally, the finished product is retrieved from the Builder.

The following diagram shows these relationships:

Figure 3.1 : Builder pattern

We start off with the abstract VehicleBuilder class:

public abstract class VehicleBuilder
{
    public virtual void BuildBody() {}
    public virtual void BuildBoot() {}
    public virtual void BuildChassis() {}
    public virtual void BuildPassengerArea() {}
    public virtual void BuildReinforcedStorageArea() {}
    public virtual void BuildWindows() {}

    public abstract IVehicle Vehicle {get;}
}

Note how this class defines all possible 'build' methods for both cars and vans, and provides empty implementations for each as a default. The abstract Vehicle property getter is for returning the finished vehicle.

The CarBuilder class inherits from VehicleBuilder and overrides the appropriate methods:

public class CarBuilder : VehicleBuilder
{
    private AbstractCar carInProgress;

    public CarBuilder(AbstractCar car)
    {
        carInProgress = car;
    }

    public override void BuildBody()
    {
        Console.WriteLine("building car body");
    }

    public override void BuildBoot()
    {
        Console.WriteLine("building car boot");
    }

    public override void BuildChassis()
    {
        Console.WriteLine("building car chassis");
    }

    public override void BuildPassengerArea()
    {
        Console.WriteLine("building car passenger area");
    }

    public override void BuildWindows()
    {
        Console.WriteLine("building car windows");
    }

    public override IVehicle Vehicle
    {
        get
        {
            return carInProgress;
        }
    }
}    

Note that the BuildReinforcedStorageArea() method was not overridden since it is not applicable to cars. The VanBuilder class overrides the appropriate methods to build a van:

public class VanBuilder : VehicleBuilder
{
    private AbstractVan vanInProgress;

    public VanBuilder(AbstractVan van)
    {
        vanInProgress = van;
    }

    public override void BuildBody()
    {
        Console.WriteLine("building van body");
    }

    public override void BuildChassis()
    {
        Console.WriteLine("building van chassis");
    }

    public override void BuildReinforcedStorageArea()
    {
        Console.WriteLine("building van storage area");
    }

    public override void BuildWindows()
    {
        Console.WriteLine("building van windows");
    }

    public override IVehicle Vehicle
    {
        get
        {
            return vanInProgress;
        }
    }
}

Note that the BuildBoot() and BuildPassengerArea() methods were not overridden since they are not applicable to vans.

The VehicleDirector abstract class requires a VehicleBuilder object passed to its Build() method for implementation by subclasses:

public abstract class VehicleDirector
{
    public abstract IVehicle Build(VehicleBuilder builder);
}

The CarDirector class inherits from VehicleDirector and provides the step-by-step process for building a car:

public class CarDirector : VehicleDirector
{
    public override IVehicle Build(VehicleBuilder builder)
    {
        builder.BuildChassis();
        builder.BuildBody();
        builder.BuildPassengerArea();
        builder.BuildBoot();
        builder.BuildWindows();
        return builder.Vehicle;
    }
}

The VanDirector class provides the step-by-step process for building a van:

public class VanDirector : VehicleDirector
{
    public override IVehicle Build(VehicleBuilder builder)
    {
        builder.BuildChassis();
        builder.BuildBody();
        builder.BuildReinforcedStorageArea();
        builder.BuildWindows();
        return builder.Vehicle;
    }
}

As an example of how to use the above classes, let's assume we want to build a Saloon car:

AbstractCar car = new Saloon(new StandardEngine(1300));
VehicleBuilder builder = new CarBuilder(car);
VehicleDirector director = new CarDirector();
Vehicle v = director.Build(builder);
Console.WriteLine(v);
Console.Read();

You can see the required Builder object is constructed and passed to the required Director object, after which we invoke the method to build the product and then retrieve the finished article. The output should show:

Building car chassis
Building car body
Building car passenger area
Building car boot
Building car windows
Saloon (StandardEngine (1300), Unpainted)

4. Factory Method

 Type: Creational

Purpose: Define an interface for creating an object, but let subclasses decide which class to instantiate.

You will recall from the introduction the following class hierarchy for the vehicles made by the Foobar Motor Company:

Figure 4.1 : IVehicle class hierarchy

When we need to instantiate a particular type of vehicle (such as a Coupe) it is often more flexible to define a separate class whose responsibility it is to manage the instantiation. This separate class is known as a Factory.

The Factory Method pattern defines an abstract class which serves as the 'factory' and that has an abstract method within to determine what product (in our case vehicle) to instantiate. Concrete subclasses of the factory make that determination. Here is how the Factory Method pattern could be used with the IVehicle class hierarchy:

Figure 4.2 : Factory Method pattern

In the above diagram we can see that we have created an abstract VehicleFactory class which has two concrete subclasses, CarFactory and VanFactory. Let us look at how VehicleFactory is defined:

public abstract class VehicleFactory
{

    public enum DrivingStyle
    {
        Economical, Midrange, Powerful
    }

    public virtual IVehicle Build(DrivingStyle style, VehicleColour colour)
    {
        IVehicle v = SelectVehicle(style);
        v.Paint(colour);
        return v;
    }

    // This is the "factory method"
    protected internal abstract IVehicle SelectVehicle(DrivingStyle style);
}

VehicleFactory contains the public method Build() that takes as arguments the driving style (Economical, Midrange or Powerful) and the colour that the vehicle should be painted. The Build() method calls the protected abstract SelectVehicle() method, which is the "factory method" after which the pattern is named. The implementation of SelectVehicle() is therefore delegated to the subclasses such that each subclass determines the specific type of vehicle to instantiate. The method is protected because we only want subclasses to utilise it; it is not intended to be invoked by clients.

Here is the CarFactory concrete subclass:

public class CarFactory : VehicleFactory
{
    protected internal override IVehicle SelectVehicle, (DrivingStyle style)
    {
        if (style == DrivingStyle.Economical)
        {
            return new Saloon(new StandardEngine(1300));
        }
        else if (style == DrivingStyle.Midrange)
        {
            return new Coupe(new StandardEngine(1600));
        }
        else
        {
            return new Sport(new TurboEngine(2000));
        }
    }
}

As you can see, the SelectVehicle() method is implemented such that it works out from the supplied arguments exactly which type of car should be instantiated and returned.

The VanFactory is similar, using the argument to decide which van to instantiate and return:

public class VanFactory : VehicleFactory
{
    protected internal override IVehicle SelectVehicle, (DrivingStyle style)
    {
        if ((style == DrivingStyle.Economical) || (style == DrivingStyle.Midrange))
        {
            return new Pickup(new StandardEngine(2200));
        }
        else
        {
            return new BoxVan(new TurboEngine(2500));
        }
    }
}

Client programs instantiate the required factory and call its Build() method:

// I want an economical car, coloured blue...
VehicleFactory carFactory = new CarFactory();
Vehicle car = carFactory.Build(VehicleFactory.DrivingStyle.Economical, VehicleColour.Blue);
Console.WriteLine(car);
 
// I am a "white van man"...
VehicleFactory vanFactory = new VanFactory();
Vehicle van = vanFactory.Build(VehicleFactory.DrivingStyle.Powerful, VehicleColour.White);
Console.WriteLine(van);

Console.Read();

You should see the following output:

Saloon (StandardEngine (1300), Blue)
BoxVan (TurboEngine (2500), White)

Using static factory methods

A common and useful variation is to define a static factory method. Let's assume we define the following additional enum in the VehicleFactory class:

public enum Category

{

    Car, Van

}

Now we can define the following static Make() method also in VehicleFactory that works out which subclass to instantiate:

public static IVehicle Make(Category category, DrivingStyle style, VehicleColour colour) {
    VehicleFactory factory = null;
 
    if (category == Category.Car) {
        factory = new CarFactory();

    } else {
        factory = new VanFactory();
    }
 
    return factory.Build(style, colour);
}
 

Using the static Make() method is very straightforward:

// Create a red sports car...
Vehicle sporty = VehicleFactory.Make(VehicleFactory.Category.Car, VehicleFactory.DrivingStyle.Powerful, Colour.Red);
Console.WriteLine(sporty);

This should give the following output:

Sport (TurboEngine (2000), Red)

5. Prototype

Type: Creational

Purpose: Specify the kinds of objects to create using a prototypical instance, and create new objects by copying the prototype.

We shall assume in this chapter that instantiating car and van objects is a time-consuming process, and we therefore need to find a way of speeding up instantiation time whenever we need a new vehicle object. Here is a reminder of the IVehicle class hierarchy:

Figure 5.1 : IVehicle class hierarchy

One approach that may improve instantiation time is to utilise the C# cloning facilities. We will therefore specify that the IVehicle interface extends ICloneable and define the method Clone(). Code to perform the cloning will then be defined in AbstractVehicle. This chapter thus uses a modified version of the IVehicle interface and AbstractVehicle class as listed below, where the additional code is indicated in bold:

public interface IVehicle : ICloneable
{
    IEngine Engine { get; }
    VehicleColour Colour { get; }
    void Paint(VehicleColour colour);
}

public abstract class AbstractVehicle : IVehicle
{
    private IEngine engine;
    private VehicleColour colour;

    public AbstractVehicle(IEngine engine) : this(engine, VehicleColour.UNPAINTED)
    {
    }

    public AbstractVehicle(IEngine engine, VehicleColour colour)
    {
        this.engine = engine;
        this.colour = colour;
        // ... followed by lots of time-consuming stuff
    }

    public virtual IEngine Engine
    {
        get
        {
            return engine;
        }
    }

    public virtual VehicleColour Colour
    {
        get
        {
            return colour;
        }
    }

    public virtual void Paint(VehicleColour colour)
    {
        this.colour = colour;
    }

    public virtual object Clone()    {        return this.MemberwiseClone();    }

    public override string ToString()
    {
        return this.GetType().Name + " (" + engine + ", " + colour + ")";
    }

}

The clone() method invokes the C# MemberwiseClone() method to perform the cloning of the receiving object.

None of the car or van subclasses needs to change since they inherit from IVehicle at the root of the hierarchy.

We will now define a VehicleManager class that will create the initial vehicles from which we can obtain clones:

public class VehicleManager
{
    private IVehicle saloon, coupe, sport, boxVan, pickup;

    public VehicleManager()
    {
        // For simplicity all vehicles use same engine type...
        saloon = new Saloon(new StandardEngine(1300));
        coupe = new Coupe(new StandardEngine(1300));
        sport = new Sport(new StandardEngine(1300));
        boxVan = new BoxVan(new StandardEngine(1300));
        pickup = new Pickup(new StandardEngine(1300));
    }

    public virtual IVehicle CreateSaloon()
    {
        return (IVehicle)saloon.Clone();
    }

    public virtual IVehicle CreateCoupe()
    {
        return (IVehicle)coupe.Clone();
    }

    public virtual IVehicle CreateSport()
    {
        return (IVehicle)sport.Clone();
    }

    public virtual IVehicle CreateBoxVan()
    {
        return (IVehicle)boxVan.Clone();
    }

    public virtual IVehicle CreatePickup()
    {
        return (IVehicle)pickup.Clone();
    }

}

Client programs can use VehicleManager as follows:

VehicleManager manager = new VehicleManager();
Vehicle saloon1 = manager.CreateSaloon();
Vehicle saloon2 = manager.CreateSaloon();
Vehicle pickup1 = manager.CreatePickup();

A drawback of VehicleManager as coded is that it always instantiates at least one vehicle of each type as part of the construction process. If not all types of vehicles will be needed, a more efficient technique would be to lazy-load by only instantiating the first time each is needed. This is illustrated in the modified version of the class (which we will call VehicleManagerLazy) below:

public class VehicleManagerLazy
{

    private IVehicle saloon, coupe, sport, boxVan, pickup;

    public VehicleManagerLazy()
    {
    }

    public virtual IVehicle CreateSaloon()
    {
        if (saloon == null)
        {
            saloon = new Saloon(new StandardEngine(1300));
        }
        return (IVehicle)saloon.Clone();
    }

    public virtual IVehicle CreateCoupe()
    {
        if (coupe == null)
        {
            coupe = new Coupe(new StandardEngine(1300));
        }
        return (IVehicle)coupe.Clone();
    }

    public virtual IVehicle CreateSport()
    {
        if (sport == null)
        {
            sport = new Sport(new StandardEngine(1300));
        }
        return (IVehicle)sport.Clone();
    }

    public virtual IVehicle CreateBoxVan()
    {
        if (boxVan == null)
        {
            boxVan = new BoxVan(new StandardEngine(1300));
        }
        return (IVehicle)boxVan.Clone();
    }

    public virtual IVehicle CreatePickup()
    {
        if (pickup == null)
        {
            pickup = new Pickup(new StandardEngine(1300));
        }
        return (IVehicle)pickup.Clone();
    }

}

Before a clone is returned, a check is made to ensure that the 'prototype' object exists, and it will be instantiated if necessary. From then on it just clones the previously instantiated object. Client programs can use VehicleManagerLazy in the same way as before:

VehicleManagerLazy manager = new VehicleManagerLazy();
 
Vehicle saloon1 = manager.CreateSaloon();
Vehicle saloon2 = manager.CreateSaloon();
Vehicle pickup1 = manager.CreatePickup();

6. Singleton

Type: Creational

Purpose: Ensure a class allows only one object to be created, providing a single point of access to it.

The Foobar Motor Company, in common with all vehicle manufacturers, needs to stamp a unique serial number on all vehicles they produce. They want to model this requirement ensuring that there is just one easy place where the next available serial number can be obtained. If we were to have more than one object that generates the next number there is a risk that we could end up with separate numbering sequences, so we need to prevent this.

The Singleton pattern provides a way of ensuring that only one instance of a particular class can ever be created. So how can we stop other objects from just invoking new multiple times? There are several ways of accomplishing this, and the "traditional" approach that you may often encounter is to make your constructor private but provide a public static getter method that returns a static instance of the Singleton class. This is how it could look:

public class SerialNumberGenerator
{
    // static members
    private static volatile SerialNumberGenerator instance;

    public static SerialNumberGenerator Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new SerialNumberGenerator();
            }
            return instance;
        }
    }


    // instance variables
    private int count;

    // private constructor
    private SerialNumberGenerator()
    {
    }

    // instance methods
    public virtual int NextSerial
    {
        get
        {
            return ++count;
        }
    }

}

Note that the Instance getter will only instantiate the object once and so the same instance will always be returned. The constructor is private to prevent client programs from calling new, thus enforcing the fact that only one object can ever be created, since they can only go through the Instance getter. The singleton could be used thus:

Console.WriteLine("next serial: " + SerialNumberGenerator.Instance.NextSerial);
Console.WriteLine("next serial: " + SerialNumberGenerator.Instance.NextSerial);
Console.WriteLine("next serial: " + SerialNumberGenerator.Instance.NextSerial);