Object Instantiation in C#: Part IV - The Builder Pattern

Before reading this article kindly go through the previous parts.

What is A Builder in C#?

The difference between the abstract factory and the builder is that the abstract factory is primarily concerned with what is being built and the builder is primarily concerned with how something is being built.

In this example, we'll be building two different kinds of cars, a station wagon and a race car.  The cars are instances of the same Car class with different parts.

public abstract class Tire {}  
public abstract class Engine { }  
public abstract class Frame { }  
  
public class Car  
{  
  
    private Tire[] m_tires;  
    private Engine m_engine;  
    private Frame m_frame;  
  
    public Tire[] Tires  
    {  
        get { return m_tires; }  
        internal set { m_tires = value; }  
    }  
  
    public Engine Engine  
    {  
        get { return m_engine; }  
        internal set { m_engine = value; }  
    }  
  
    public Frame Frame  
    {  
        get { return m_frame; }  
        internal set { m_frame = value; }  
    }  
}

Here are the different definitions for each type of part

internal class RacingTire : Tire { }  
internal class SixCylinderEngine : Engine { }  
internal class RacingFrame : Frame { }  
internal class NormalTire : Tire { }  
internal class FourCylinderEngine : Engine { }  
internal class StationWagonFrame : Frame { }

Next we will define an abstract factory that will build an instance of a car but instead of focusing on the type of car being built, we'll focus on the parts so instead of calling it an abstract factory, we'll call it a builder.

Here is our abstract builder contract.

public abstract class CarBuilderBase  
{  
    public abstract Car Build();  
}

And here is our concrete builder.

public class CarBuilder : CarBuilderBase  
{  
  
    public CarBuilder(CarBuilderBase strategy)  
    {  
        m_strategy = strategy;  
    }  
  
    private CarBuilderBase m_strategy;  
  
    public CarBuilderBase Strategy  
    {  
        get { return m_strategy; }  
        set { m_strategy = value; }  
    }  
  
    public override Car Build()  
    {  
        return m_strategy.Build();  
    }  
}

Now, we'll define our two builders which will be responsible for how a car is constructed.

internal class StationWagonBuilder : CarBuilderBase  
{  
    public override Car Build()  
    {  
        Car result = new Car();  
        result.Engine = new FourCylinderEngine();  
        result.Frame = new StationWagonFrame();  
        result.Tires = new Tire[]  
        {  
            new NormalTire(),  
            new NormalTire(),  
            new NormalTire(),  
            new NormalTire()  
        };  
  
        return result;  
    }  
}  
  
internal class RacingCarBuilder: CarBuilderBase  
{  
   public override Car Build()  
    {  
        Car result = new Car();  
        result.Engine = new SixCylinderEngine();  
        result.Frame = new RacingFrame();  
        result.Tires = new Tire[]  
        {  
            new RacingTire(),  
            new RacingTire(),  
            new RacingTire(),  
            new RacingTire()  
        };  
  
        return result;  
    }  
}

So now, in our implementing code we instantiate objects just as we do with the abstract factory pattern.

CarBuilder autoFactory = new CarBuilder(new RacingCarBuilder());  
Car result = autoFactory.Build();  
autoFactory.Strategy = new StationWagonBuilder();  
Car stationWagon = autoFactory.Build();

To better understand the article please go through the next parts also.


Similar Articles