Tuesday, December 4, 2012

Creational Patterns: Builder

In this post I am going to show you how to implement the Builder design pattern in Java.

Solution offered by the pattern

This pattern separates the construction of a complex object from its representation, in a way that the same construction process allows to create different representations. 
To do so we must use an object, the Director, that determines the product construction logic and sends those instruction to an object, the Builder, responsible for the product construction. Since the product to be carrued out are of different nature, there will be particular Builders for every kind of product, but one only Director. In the process of construction the Director calls invokes the chosen Builder's methods based on the type of the desired product (the Builders should implement a common interface to allow the Director to interact with all those).

Pattern Structure


Builder Design Pattern Class Diagram
Design pattern application - schema model


Builder Application  Balls schema

Partecipants

  • Builder: Abstract class BallBuilder:
- Declares an interface for the operations that create the parts of the object Product;
- Implements the default operations for every operation. 

  •  ConcreteBuilder: the classes BasketBallBuilder and VolleyBallBuilder:
- They provide the concrete operations for the interface correspondant to bhe Builder;
- Construct and assemblate the parts of a Product; 
- Provides a method that returns the created Product. 

  • Director: class Director 
- Construct the Product invoking the methods of the interface of the builder.

  • Product: classes Ball, BasketBall and VolleyBall
- Represents the complex object in construction. The ConcreteBuilders return the internal representation of the products;
- Includes classes that defines the parts of a Product. 

 Code Description
I've declared the abstract class BallBuilder extended by the ConcreteBuilders for the construction of every kind of ball. The class BallBuilder contains all the methods that the ConcreteBuilder could override, and they do implement only those necessary to construct the Product; this is why the BallBuilder provides all the methods a default code, in this case null code; the only abstract method is getBall() that all the ConcreteBuilders must implement to return the constructed object.

 
package com.fa.builderdesignpattern.builder;

import com.fa.builderdesignpattern.product.Ball;

public abstract class BallBuilder {
 
    
    public abstract Ball getBall();
    public void createNewBallProduct() {};
    public void buildWeight() {};
    public void buildCircumference() {};
    public void buildColor() {};
    public void buildPrice() {};
 
}

This class presents a set of methods declared with a default implementation and the first method declared abstract that must be implement from the builders to return the different kind of objects.
The methods presented are those needed to construct the product and the abstract one that returns the constructed product of type Ball.
The following classes are the ConcreteBuilders and contain the code necessary to return the instantiated product:
 
package com.fa.builderdesignpattern.builder;

import com.fa.builderdesignpattern.product.Ball;
import com.fa.builderdesignpattern.product.BasketBall;

public class BasketBallBuilder extends BallBuilder {

 protected Ball basketBall;
 
 @Override
 public void buildWeight() {
  basketBall.setWeight("624 g");
 }

 @Override
 public void buildCircumference() {
  basketBall.setCircumference("75-75.88 cm");
 }

 @Override
 public void buildColor() {
  basketBall.setColor("Orange surface with black ribs and a possible logo is the traditional color scheme of basketballs.");
 }

 @Override
 public void buildPrice() {
  basketBall.setPrice("$95");
 }

 @Override
 public Ball getBall() {
  return basketBall;
 }

 @Override
 public void createNewBallProduct() {
  basketBall = new BasketBall();
 }

}

 
package com.fa.builderdesignpattern.builder;

import com.fa.builderdesignpattern.product.Ball;
import com.fa.builderdesignpattern.product.VolleyBall;

public class VolleyBallBuilder extends BallBuilder {

 Ball volleyBall;
 
 @Override
 public void buildWeight() {
  volleyBall.setWeight("270 g");
 }

 @Override
 public void buildCircumference() {
  volleyBall.setCircumference("65-67 cm");
 }

 @Override
 public void buildColor() {
  volleyBall.setColor("Volleyballs may be solid white or a combination of two or three different easily distinguishable colors.");
 }

 @Override
 public void buildPrice() {
  volleyBall.setPrice("$60");
 }

 @Override
 public Ball getBall() {
  return volleyBall;
 }

 @Override
 public void createNewBallProduct() {
  volleyBall = new VolleyBall();
 }
}

As you can see the concrete builders do override the default behaviour defined in the AbstractBuilder and the method getBall() that was declared abstract in the AbstractBuilder is now implemented to return the constructed Ball. The Director class receives a reference to a ConcreteBuilder and will execute its methods to construct the Product. The Director in this example has a method createNewBallProduct() to instantiate a new Ball and a method constructBall() that is called to set the properties of the new created product. Finally the method getBall() returns the new instantiated Ball.
package com.fa.builderdesignpattern.director;

import com.fa.builderdesignpattern.builder.BallBuilder;
import com.fa.builderdesignpattern.product.Ball;

public class Director {
 
 private BallBuilder ballBuilder;
  
    public void setBallBuilder(BallBuilder bb) { ballBuilder = bb; }
    public Ball getBall() { return ballBuilder.getBall(); }
 
    public void constructBall() {
     ballBuilder.createNewBallProduct();
     ballBuilder.buildWeight();
     ballBuilder.buildCircumference();
     ballBuilder.buildColor();
     ballBuilder.buildPrice();
    }
 
}

Note that the Director is not aware of which type of ConcreteBuilder it is working with because it is managed through the common interface of the Builders (BallBuilder). The class BuilderExample contains the main that demonstrates the pattern realizing an instance of both the Builders. Note that the type of ConcreteBuilder is chosen only at this level. Lets now see the Products: in this example I have defined an abstract superclass Ball that is extended by the concrete Products VolleyBall and BasketBall.
package com.fa.builderdesignpattern.product;

public abstract class Ball {
 
 private String weight = "";
 private String circumference = "";
 private String color = "";
 private String price = "";
 
 public void setWeight(String weight) { this.weight = weight; }
 
 public void setCircumference(String circumference) { this.circumference = circumference; }
 
 public void setColor(String color) { this.color = color; }

 public void setPrice(String price) { this.price = price; }
 
 public abstract String bounce();
 
 public String toString() {
  return "weight: " + weight +
    ", circumference: " + circumference + 
    ", color: " + color + 
    ", price: " + price + 
    ", " + bounce();
    
 }
}

package com.fa.builderdesignpattern.product;

public class BasketBall extends Ball {

 @Override
 public String bounce() {
  return "BasketBall BOUNCE"; 
 }

}

package com.fa.builderdesignpattern.product;

public class VolleyBall extends Ball {

 @Override
 public String bounce() {
  return "VolleyBall BOUNCE"; 
 }

}

The abstract class Ball defines the properties and methods common to the concrete Products and defines the abstract method bounce() that its child override defining their own behaviours. Example execution
BasketBall: weight: 624 g
circumference: 75-75.88 cm
color: Orange surface with black ribs and a possible logo is the traditional color scheme of basketballs.
price: $95
BasketBall BOUNCE

VolleyBall: weight: 270 g
circumference: 65-67 cm
color: Volleyballs may be solid white or a combination of two or three different easily distinguishable colors.
price: $60
VolleyBall BOUNCE