Friday, May 20, 2011

Builder pattern

Builder pattern is used to construct a complex object step by step and the final step will return the object. The process of constructing an object should be generic so that it can be used to create different representations of the same object.

For example, you can consider construction of a home. Home is the final end product (object) that is to be returned as the output of the construction process. It will have many steps, like basement construction, wall construction and so on roof construction. Finally the whole home object is returned. Here using the same process you can build houses with different properties.

GOF says,
“Separate the construction of a complex object from its representation so that the same construction process can create different representations” [GoF 94]

Sample builder design pattern implementation in Java API

DocumentBuilderFactory , StringBuffer, StringBuilder are some examples of builder pattern usage in java API.

Components in Builder Pattern:

Builder
Abstract interface for creating objects (product).

Concrete Builder
Provide implementation for Builder. Construct and assemble parts to build the objects.

Director
The Director class is responsible for managing the correct sequence of object creation. It receives a Concrete Builder as a parameter and executes the necessary operations on it.

Product
The final object that will be created by the Director using Builder.

Builder Pattern and other Creational Patterns
Unlike creational patterns that construct products in one shot,the builder pattern constructs the product step by step.

Sometimes creational patterns are complementary.Builder can use one of the other patterns to implement which components get built.Abstract Factory,Builder,and Prototype can use Singleton in their implementations.[GoF,p81,134]

Builder focuses on constructing a complex object step by step.Abstract Factory emphasizes a family of product objects(either simple or complex).Builder returns the product as a final step,but as far as the Abstract Factory is concerned,the product gets returned immediately.[GoF,p105]. See - Difference between abstract factory pattern and builder pattern.

Builder often builds a composite[GoF,p106]

Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed. 

Sample Java Source Code for Builder Pattern

Let us look at an example

/** "Product" */
class HolidayPackage {
 private String flightBookingRef = "";
 private String carBookingRef = "";
 private String hotelBookingRef = "";
 
 //setters and getters

}
 
/** "Abstract Builder" */
abstract class HolidayPackageBuilder {
 
 protected HolidayPackage holidayPackage;
 
 public HolidayPackageBuilder(){
  holidayPackage = new HolidayPackage();
 }
 
 public abstract void build();

}


/** "ConcreteBuilder" */
public class BookCarBuilder extends HolidayPackageBuilder {
 
 public void build(){
  bookCar();
 }
 
 private void bookCar() {
  String carBookingRef = null;
  
  // functionality to book the car and
  // get the ref and assign it to carBookingRef
  // let us give some hard coded value to carBookingRef
  
  carBookingRef = "SPC3778/09";
  
  holidayPackage.setCarBookingRef(carBookingRef);
  
  System.out.println("Car has been successfully booked - "+carBookingRef);
 }
 

}

class BookFlightBuilder extends HolidayPackageBuilder {
 
 public void build(){
  bookFlight();
 }
 
 private void bookFlight() {
  String flightBookingRef = null;
  
  // functionality to book the flight and
  // get the ref and assign it to flightBookingRef
  // let us give some hard coded value to flightBooking Ref
  
  flightBookingRef = "SPF3778/09";
  
  holidayPackage.setFlightBookingRef(flightBookingRef);
  
  System.out.println("Flight has been successfully booked - "+flightBookingRef);
 }
  
}

public class BookHotelBuilder  extends HolidayPackageBuilder {
 
 public void build(){
  bookHotel();
 }
 
 private void bookHotel() {
  String hotelBookingRef = null;
  
  // functionality to book the hotel and
  // get the ref and assign it to hotelBookingRef
  // let us give some hard coded value to hotelBookingRef
  
  hotelBookingRef = "SPH3778/09";
  
  holidayPackage.setHotelBookingRef(hotelBookingRef);
  
  System.out.println("Hotel has been successfully booked - "+hotelBookingRef);
 }
 
}

public class ConcreteHolidayPackageBuilder extends HolidayPackageBuilder {
 
 BookFlightBuilder bookFlightBuilder;
 BookCarBuilder bookCarBuilder;
 BookHotelBuilder bookHotelBuilder;
 
 public ConcreteHolidayPackageBuilder(){
  bookFlightBuilder = new BookFlightBuilder();
  bookCarBuilder = new BookCarBuilder();
  bookHotelBuilder = new BookHotelBuilder();
 }
 
 public void build(){
  bookCompletePackage();  
 }
 
 private void bookCompletePackage() {
  bookFlightBuilder.build();
  bookCarBuilder.build();
  bookHotelBuilder.build();
 }
 
  
}



/** "Director" */
class HolidayPackageReader {
 
 private HolidayPackageBuilder holidayPackageBuilder;
 
 public void setHolidayPackageBuilder(HolidayPackageBuilder holidayPackageBuilder){
  this.holidayPackageBuilder = holidayPackageBuilder;
 }


 public void build() {     
  holidayPackageBuilder.build();   
 }
}



public class BuilderPatternDemo {
 
 public static void main(String[] args) {
  
  // You can book the complete package or book them seperately also.
  HolidayPackageBuilder builder = new ConcreteHolidayPackageBuilder();
  
  HolidayPackageReader packageReader = new HolidayPackageReader();
  packageReader.setHolidayPackageBuilder(builder);
  
  packageReader.build();
      
 }
}

Advantages :
1. Encapsulate the way a complex object is constructed.
2. Allows objects to be constructed in a multistep and varying processes.
3. Hides the internal representation of the product from the client.
4. Product implementation can be swapped in and out because the client only sees the abstract interface.


Disadvantages:
1. Often used for building complex structures.
2. Constructing objects requires more domain knowledge of the client than when using a factory.

No comments:

Post a Comment

Chitika