Design Patterns Series 12 - Builder Pattern

Today we have a date with another pattern that give you a clever way of dealing with adapting the process of creating objects. previous post we explored The Template Method pattern today we will explore its twin, Builder Pattern.

Builder Pattern:

We use the Template Method Pattern when we have a multi-steps algorithm with in a certain order and we want to customize some steps. But what about if the number of steps and its order differs from one case to another?!!!!!.

In Builder Pattern you don't inherit a template method anymore and then customize that method to create your own object. Instead, to create different types of objects, you allow client code to use different builder objects. The client code now sets the number and sequence of the steps in the algorithm, and selects which builder to use.

The Builder Pattern let you "Separate the construction of a complex object from its representation so that the same construction processes can create different representations."

The main difference between the Template Method Pattern and the Builder Pattern is in who creates the sequence of steps in the algorithm. In the Template Method, you do, and sub-classes can make alteration. In the Builder Pattern you provide to create various objects that embody that algorithm.

Use the Builder Pattern  when you want client code to have control over the construction process but want to be able to end up with different kinds of objects. In other words, when the client code has control over the construction process but you still want to be able to construct different kinds of objects, the Builder Pattern should spring to mind.

The pattern is similar to Factory Pattern, but the Factory Pattern can be more involved, and it centers on a single step creation process, not a configurable sequence of steps, as Builder Pattern. When you use the Builder Pattern, the client code is in charge of the construction process, and it's up to your builders to do what the client code wants.

If we want to check how the Builder Pattern works,let's remember the booking algorithm that we represented to build the Template Method Pattern in the previous post. The booking algorithm steps as its for flights and hotels but flight booking has different number of steps and sequence from hotels booking. So the hotel client will construct his own booking algorithm, and flight client too.

First we will create IBookingBuilder interface that all booking builder have to implement. It lists the methods that all booking builders must implement. from CheckValidCreditCard() to BookingConfirmationCode(), as well as GetBookingBuildable().( check previous post to know Booking algorithm steps).

IBookingBuilder interface
public interface IBookingBuilder
{
    void AddCheckValidCreditCard();
    void AddCheckCardHolder();
    void AddCheckCardBalance();
    void AddCheckValidBooking();
    void AddDoBooking();
    void AddBookingConfirmationCode();
    IBooking GetConfiguredBooking();
}
As we explained earlier, we have two types of booking, one for flights and another for hotels, so we have to create two builders, one for each type. But before we create our booking builders we have to store the steps of booking algorithm to the client be able to select the steps sequence he wants. Here I created an enumeration for this purpose.

Steps enumeration
public enum Steps
{
    CheckValidCreditCard = 1,
    CheckCardHolder = 2,
    CheckCardBalance = 3,
    CheckValidBooking = 4,
    DoBooking = 5,
    BookingConfirmationCode = 6
}
Note the order of enumeration items is the default order of booking algorithm steps.
Now we will create one of our builders that implement IBookingBuilder interface. let's start with builder of hotel booking.

HotelBookingBuilder class
public class HotelBookingBuilder : IBookingBuilder
{
    List<Steps> steps;
    private HotelBooking booker;

    public HotelBookingBuilder()
    {
        booker = new HotelBooking();
        steps = new List<Steps>();
    }
    public void AddCheckValidCreditCard()
    {
        steps.Add(BookingSteps.Steps.CheckValidCreditCard);
    }
    .
    .
    .
    public IBooking GetConfiguredBooking()
    {
       booker.LoadSteps(steps);
       return booker;
    }
}
Note we created a list of Steps enumeration and inside each method we add the appropriate step into this list. The list items are the steps of booking algorithm and the order of items inside this list is the new order of the booking algorithm steps.

When the client want to get the booking object it has configured from the builder, it calls the builder's GetConfiguredBooking() method. When that method is called, you know the construction process is complete, so you can configure the booking object by passing it the list of steps it should execute.

Now we completed  the builder, which lets the client code configure the booking algorithm by adding various steps, and in whatever order, as required. So how about creating the Booking class that the hotel/flight will based on.

We agree that hotel or flight must have a Book() method that run the booking algorithm, So we will create an interface with this method to be implemented by hotel or flight.

IBooking interface
public interface IBooking
{
    void Book();
}
Now is the time for creating HotelBooking class

HotelBooking interface
public class HotelBooking : IBooking
{
    List<Steps> _steps;

    public void Book()
    {
     foreach (var step in _steps)
     {
         switch(step)
         {
             case BookingSteps.Steps.CheckValidCreditCard:
                 CheckValidCreditCard();
                 break;
                 case BookingSteps.Steps.CheckCardHolder:
                 CheckCardHolder();
                 break;
                 .
                 .
                 .                 
         }
     }
    }
    public void LoadSteps(List<Steps> steps)
    {
        _steps = steps;
    }
    public virtual void CheckValidCreditCard()
    {
        Console.WriteLine("Checking valid credit card....");
    }
    .
    .
    .
}
When the client want to perform hotel booking it will call Book() method which will iterate over Steps list and call the appropriate method for each step. The FlightBooking class will be the same but with different implementation for each step in booking algorithm.

To test the Builder Pattern we create an instance of IBookingBuilder for flights or hotels, specify the booking algorithm steps, Get the configured booking algorithm, and call its Book() method.
IBookingBuilder bookingBuilder;
Console.Write("Do you want to book hotel (H) or flight (F)?");
String bookingtype = Console.ReadLine();
switch(bookingtype)
{
    case "F":
        bookingBuilder = new FlightBookingBuilder();
        bookingBuilder.AddBookingConfirmationCode();
        bookingBuilder.AddCheckCardHolder();
        bookingBuilder.AddDoBooking();
        break;
    case "H":
        bookingBuilder = new HotelBookingBuilder();
        bookingBuilder.AddCheckCardBalance();
        bookingBuilder.AddCheckCardHolder();
        bookingBuilder.AddCheckValidCreditCard();
        bookingBuilder.AddDoBooking();
        break;
    default:
        return;
}
IBooking bookingBuildable = bookingBuilder.GetConfiguredBooking();
bookingBuildable.Book();
If we run this code Flights(F) we will get
Confirm Flight Booking....
Checking Credit card holder....
Do Flight Booking....
and for Hotels(H) we will get
Checking Credit Card Balance....
Checking Credit card holder....
Checking valid credit card....
Do Hotel Booking....
From this result you can see how the number of steps and the sequence of them are different.

you can download the full source code here

Comments

Popular posts from this blog

ASP.Net MVC : ActionLink with bootstrap icon

ASP.Net MVC : Conditional Validation using ValidationAttribute

Android : How to change progress bar color at runtime programmatically?