How to implement Builder pattern in Java

Let’s prepare Vanjaram Fish Curry , a complex object in Java.

Let’s use Builder Pattern right out of the books of the Gang of Four.

In fact I bought this book recently and used the recipe given by them.

Let’s start with the client code . This I believe gives a better perspective to decode a design pattern.

In this below design pattern , a FishCurryLover instructs a VanjaramFishCurryBuilder (maid) to prepare fish curry. He doesn’t even touch the fish (no instance of fish is present in the FishCurryLover class). All he does is instruct his maid, the builder to prepare fish for him according to his specific set of instructions.

FishCurry is our final product.

Here is the client code :

package creational.builder.pattern;
public class Client {
	public static void main(String a[]) {
		
                
		FishCurryLover fishCurryLover = new FishCurryLover(); 
		FishCurryBuilder vanjaramFishCurryBuilder = 
				fishCurryLover.createFishCurry(new VanjaramFishCurryBuilder()); 
		FishCurry fishcurry = vanjaramFishCurryBuilder.serveFish(); 
		
		
		System.out.println(fishcurry);
	}
}

In the above code :

We create an instance of FishCurryLover , the boy who wants fish curry.

The FishCurryLover then creates fish curry by invoking the method createFishCurry() but he actually doesn’t create it.

He takes help of VanjaramFishCurryBuilder, the maid who inherits the interface FishCurryBuilder ,the super maid. All FishCurryBuilder s should follow the same process of the super maid . They can add their own innovations but the process should be the same.

Finally the VanjaramFishCurryBuilder serves the fish.

Here is what the FishCurryLover does:

package creational.builder.pattern;
public class FishCurryLover {
	public FishCurryBuilder createFishCurry(VanjaramFishCurryBuilder builder) {
		builder.cutFish(6);
		builder.addFish("Vanjaram");
		builder.designRecipe("Vanjaram Fish Recipe");
		builder.cookForDuration("30 minutes");
		builder.prepareNoOfServes(5);
		return builder;
	}
}

All he does is sent instructions to the maid. He not even touches the fish!

Look what the VanjaramFishCurryBuilder does :

package creational.builder.pattern;
public class VanjaramFishCurryBuilder implements FishCurryBuilder {
	FishCurry fishCurry = new FishCurry();
	@Override
	public void cutFish(int noOfPieces) {
		System.out.println("Cutting fish into " + noOfPieces + " pieces");
		fishCurry.setNoOfPieces(noOfPieces);
	}
	@Override
	public FishCurry serveFish() {
		return fishCurry;
	}
	@Override
	public void addFish(String fishName) {
		System.out.println("Adding " + fishName + " to cooking vessel");
		fishCurry.setFishName(fishName);
	}
	@Override
	public void designRecipe(String recipe) {
		System.out.println("Using recipe :" + recipe);
		fishCurry.setRecipe(recipe);
	}
	@Override
	public void cookForDuration(String duration) {
		System.out.println("Cooking for " + duration);
		fishCurry.setCookingTime(duration);
	}
	@Override
	public void prepareNoOfServes(int noOfServes) {
		System.out.println("Now that it is cooked , the number of serves is" + noOfServes);
		fishCurry.setNoOfServes(noOfServes);
	}
}

She does the actual work.

Look what her super boss ‘FishCurryBuilder’ has taught her:

package creational.builder.pattern;
public interface FishCurryBuilder {
	
		
	void cutFish(int noOfPieces);
	
	void addFish(String fishName);
	
	void designRecipe(String recipe);
	
	void cookForDuration(String duration);
	
	void prepareNoOfServes(int noOfServes);
	
	
	FishCurry serveFish();
	
	
}

She has followed the exact steps as taught , isnt it?

Now lets look at our complex object ‘FishCurry’ we constructed :

package creational.builder.pattern;
public class FishCurry {
	
	
	int noOfPieces;
	
	String fishName;
	
	String recipe;
	
	String cookingTime;
	
	int noOfServes;
	public int getNoOfPieces() {
		return noOfPieces;
	}
	public void setNoOfPieces(int noOfPieces) {
		this.noOfPieces = noOfPieces;
	}
	public String getFishName() {
		return fishName;
	}
	public void setFishName(String fishName) {
		this.fishName = fishName;
	}
	public String getRecipe() {
		return recipe;
	}
	public void setRecipe(String recipe) {
		this.recipe = recipe;
	}
	public String getCookingTime() {
		return cookingTime;
	}
	public void setCookingTime(String cookingTime) {
		this.cookingTime = cookingTime;
	}
	public int getNoOfServes() {
		return noOfServes;
	}
	public void setNoOfServes(int noOfServes) {
		this.noOfServes = noOfServes;
	}
	@Override
	public String toString() {
		return "FishCurry [noOfPieces=" + noOfPieces + ", fishName=" + fishName + ", recipe=" + recipe
				+ ", cookingTime=" + cookingTime + ", noOfServes=" + noOfServes + "]";
	}
	
	
}

Running the client code , produces the below output:

Cutting fish into 6 pieces
Adding Vanjaram to cooking vessel
Using recipe :Vanjaram Fish Recipe
Cooking for 30 minutes
Now that it is cooked , the number of serves is5
FishCurry [noOfPieces=6, fishName=Vanjaram, recipe=Vanjaram Fish Recipe, cookingTime=30 minutes, noOfServes=5]

Ah ! the fish curry is ready.

It is prepared using Builder Pattern recipe right out of the books of the Gang of Four :

Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides

Lets get a bit deep into their recipe:

They call the FishCurryLover as ‘Director’

the FishCurry as ‘Product’

the FishCurryBuilder as ‘Builder’

the VanjaramFishCurryBuilder as ‘ConcreteBuilder’

We could have added a ‘ConcreteProduct’ as well by declaring FishCurry as an interface and ‘VanjaramFishCurry’ as a concrete product. I didn’t do that for simplicity.

A Director instructs a builder to construct a complex product. By doing so the construction of the complex object is delegated to the builder and this provides loose coupling between construction and representation.

Here is the description from their book:

“Seperate the construction of a complex object from its representation so that the same construction process can create different representations”

Here “the same construction process can create different representations” means you can use different Builders who follow the same process (defined by the builder interface) to create different Products.

You can create a MackerelFishCurryBuilder to create a MackeralFishCurry by using the same process listed in FishCurryBuilder interface.

So when should you use Builder pattern.

Again quoting the GoF,

Use the Builder pattern when :

  1. the algorithm for creating a complex object should be independent of the parts that make up the object and how they are assembled. — in our case the algorithm to prepare fish curry was kept inside FishCurryLover which had no idea about the fish object and its attribute construction .
  2. the construction process must allow different representations for the object that is constructed.

Posted

in

,

by

Comments

Leave a Reply

Discover more from The Full Stack Developer

Subscribe now to keep reading and get access to the full archive.

Continue reading