Before reading this article kindly go through the previous parts.
- C# Object Instantiation: Part I - Constructors
- Object Instantiation in C#: Part II - Factory Methods
- Object Instantiation in C#: Part III - Abstract Factories
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.
Rakesh NairPosted Aug 22, 2007, 5:09 AM
Hi Matt, First of all thanks for sharing all this with us :) THis is my query - Why do we need the abstract builder contract: public abstract class CarBuilderBase () when we could accomplish all of this with the concrete builder: public class CarBuilder . I mean we could have an over-ridable Build method in this class and then use this to route to appropriate vrsions of the method absed on the object being instantiated. It might be a naive question that I have but nevertheless I dont quite get this. Thanks for your help, Rakesh.