CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

David Hayden [MVP C#]

         .NET Tutorials, Patterns, and Practices

Builder Design Pattern - Part 2 of 3

As mentioned in my previous post, the DbConnectionStringBuilder Class mentioned in Pro ADO.NET 2.0 allows one to build a connection string in a very object-oriented, database agnostic way by setting properties on the class and calling ToString() to get a properly formatted connection string for your datastore.

The DbConnectionStringBuilder Class is fashioned after the Builder Design Pattern, which is one of several Construction Patterns mentioned in my favorite design patterns book, Design Patterns in C# by Steven John Metsker.

 

Builder Design Pattern

The Builder Design Pattern moves the construction of a class to a separate builder class.  I can think of 2 reasons, but I am sure there are others, why you would want to move the construction of a class outside of the class to initiate:

  1. If the construction is complex and you wish to either reduce the size of the class, or more importantly, keep cohesion high and coupling low in the class.
  2. Allow someone to build the class in more of a step-by-step process, as we are doing in the case of the DbConnectionStringBuilder Class.

 

Builder Design Pattern Example - Reservation System

The Builder Design Pattern example in the Design Patterns in C# book is based on a hotel reservation.  I can very much appreciate the example because I used to develop and maintain a reservation system for a wholesale travel company.  One of my development responsibilities included the Electronic Data Interchange (EDI) between our hotel vendors.

In the case of one vendor, we would send down our reservations and receive confirmations via an extremely low-tech series of numbers and characters in a long string with each character position in this string representing the booking dates, number of people, type of room, names and ages of guests, etc.  It would look something like this:

 

 

This string would easily be replaced with XML these days.

As you can imagine, parsing this string of numbers and letters and then creating a Reservation requires a bit of code that is really independent of the Reservation Class itself.  No use muddying up a good, cohesive Reservation Class with a bunch of low-tech EDI code.  Better that we move these tasks to 1 or 2 separate classes, which better supports the Single-Responsibility Principle and Extract Class Refactoring.

 

ReservationBuilder Class

The ReservationBuilder Class will essentially have a number of properties on it and a single method Build() that outputs a Reservation, similar to the DbConnectionStringBuilder Class.  This way we can create the reservation step-by-step and when finished call Build() to give us our Reservation.  Here is a code snippet using [AirCode]:

[AirCode]
public class ReservationBuilder
{
    Date BookDate;
    Int32 NumberOfRooms;
    Int32 NumberOfNights;
    Int32 NumberOfAdults;
    Int32 NumberOfChildren;
    
    // ...
    
    Reservation Build();
}

 

ReservationParser Class

One might be tempted to put the parsing in the ReservationBuilder class as well, but this would be violating the Single-Responsibility Principle as well as a few best practices.  Hence we add a separate class for parsing that accepts a ReservationBuilder Class and the EDI-like string we wish to parse:

 

[AirCode]
public class ReservationParser
{
    ReservationBuilder _builder;
    
    public ReservationParser (ReservationBuilder builder);
    
    void Parse(string ediString);
}

 

The whole point of this class is to parse the string and properly set the properties on the ReservationBuilder Class we provided in the constructor.

 

Creating a Reservation

Creating a Reservation using ReservationBuilder and ReservationParser would look something like this now:

 

[AirCode]
ReservationBuilder builder = new ReservationBuilder();

new ReservationParser(builder).Parse(reservationString);

Reservation r = builder.Build();

 

In real life, ReservationBuilder and ReservationParser may be abstract classes with concrete classes created by factory methods, but that is out of the scope of this example.

 

Conclusion

If you find your classes being weighed down with a lot of construction code, you may want to move the construction of those classes to a separate builder class to keep them more cohesive and to support better reuse.  The DbConnectionStringBuilder Class is a simple example of a builder class, and the example mentioned above inspired by Design Patterns in C# by Steven John Metsker provides another example that not only involes a builder class but also a parser class.

In part 3, I will discuss the use of this pattern to build a trivial SqlSelectQueryBuilder Class.

 



Comments

Thom Lawrence said:

Another great benefit of the pattern is that you can use the same steps to build different types of object. For example, imagine a family has won a mystery holiday, but the actual holiday could be at a variety of resorts with a variety of reservation schemes. The steps to define the reservation could be the same (number of nights, bedrooms required etc), but at the end you could pass them a hotel reservation or a week's cruise.

Or whatever else (database-specific sql strings, for example). :)
# October 26, 2005 9:16 PM

David Hayden said:

Great point, Thom.

The builder provides a nice abstraction of the actual concrete Reservation Class being created. Reservation could be a base or abstract class with different concrete reservation types, like CruiseReservation, HotelReservation, CampsiteReservation, etc.
# October 27, 2005 12:56 PM

Christopher Steen said:

[Tools] VistaDB 2.1 small-footprint embedded SQL
database [Via: John
Tobler ]
ASP.NET Spiced: AJAX...
# October 28, 2005 8:39 AM
Check out Devlicio.us!

Our Sponsors

This Blog

Syndication

News

CodeBetter.Com Home