Core Java

Java Builder Design Pattern Example

1. Introduction

In this article, we will describe Java Builder Design Pattern in detail. The Builder design pattern, as its name suggests, seems to be an alternative way to develop complex objects. This can only be used if you choose to create different unchangeable objects who use the same process of object building.

This design pattern in Java is a type of Creational design pattern and it is used to create objects, similar to the Factory design pattern, which is also a Creational design pattern. In simple words, Builder design pattern is a creational design pattern it means its solves the problem related to creation of object.

You can also check a tutorial in the following video:

Java Design Patterns Tutorial – video

In java, Constructors are used to create object and can use the required parameters to create objects. Problem begins whenever an object can also be created with many parameters, some of which may be compulsory and others optional. For understanding, consider a class used to make Juice, we now require a number of items such as water, fruit, mixer, ice, straw to make Juice. Most are compulsory but some of them are optional, such as ice, straw, etc. But if we have overloaded constructor for different kind of juice then there would be more than one constructor and even worst they will accept a lot of parameter. This problem id solved by using Builder design pattern. Builder design pattern not only enhances readability but also reduces the risk of error by explicitly adding flavours and trying to make the object accessible once it has been fully created.

2. Java Design Patterns

Java design patterns were categorised further into three crucial and popularly used sub – groups that are explored below.

2.1 Creational Pattern

In object creation, creational design patterns takes place. They render the creation process much more efficient and creative. Creative patterns in particular can deliver a wide range of choices as to which objects are produced, how all these objects are produced and how they are initialised. This pattern can sometimes be labelled into either class and even object creation patterns. Although class-creation patterns effectively use inheritance in the installation process, where object-creation patterns effectively use high – level delegation to get all the job done properly. The creational design patterns are also split into six different design pattern types.

2.2 Structural Pattern

Structural pattern design characterises seven different types of design patterns. Structural design patterns are design patterns which optimise design by identifying a quick and easy way of conveying relationships between the objects. Such design patterns focus heavily upon how classes and objects could be linked to form larger frameworks. The structural design patterns try to simplify or promote the structure by understanding the difference between the structural elements.

2.3 Behavioural Pattern

These design patterns actually relate to the class-to-object communication. Behavioural design patterns are some patterns which affect communication between objects most specifically. This pattern characterises eleven different pattern classifications for interaction among objects. These design patterns are being used to deal with object algorithms, relationships and responsibilities.

In this article we will explore one of the commonly used Creational design pattern–the Builder design pattern. This article describes the idea of the Builder design pattern with a real – life example to give you a complete understanding of how well the Builder design pattern allows software developers to provide a better application. The following section develop this pattern to analyse every portion of the Builder design pattern. Furthermore, we will implement the Builder design pattern into Java program.

3. Understanding the Builder design pattern

The builder design pattern, as its name suggests, is an alternative way to build complex objects. It can only be used if you really want to create different unchangeable objects who use the same mechanism of object building. In other words, Builder design pattern allows for object level access control by acting as a pass through entity or a placeholder objectThe objective of the Builder design pattern is to isolate a complicated object from its own representation. So that different representation can develop the same construction process.

The Builder design pattern is designed to ” isolate the development of a complicated object from its own representation so that different representations can be produced by the very same construction process. ” It is used to build a complex object step by step and thus the final step is returned. The process of building an object ought to be mundane, such that different representations of the same object can be created.

This design pattern generally solves problems in object – oriented programming, that is which constructor to use while programming. We often write a lot of constructor and it’s really difficult to manage them. The multiple constructor with multiple parameter variations is called the telescopic constructor.

Let’s look at the UML class diagram before you go into more detail to understand the Builder design pattern.

Java Builder Design Pattern Example - UML Class Diagram
UML Class Diagram – Builder Pattern

The following classes, interfaces and objects are included in the UML Class Builder Design Pattern:

  • Product: In the above diagram product class defines the type of the sophisticated object that is to be created by the builder design pattern.
  • Builder: Builder is an abstract class that defines all moves needed to create a product properly. Each and every move seems to be usually abstract, since the real function of the builder class in the concrete sub classes is actually carried out. To return the final product, the GetResult() method is used. The constructing class is sometimes overtaken by a simple interface.
  • ConcreteBuilder: A number of concrete builder classes are inherited from the Builder class are seen in the above diagram. The functionality of such classes would be to develop a particular complicated product.
  • Director: In the diagram director class monitors the algorithm that produces the final product. A object in director class as well as its construct() method are called. The construct() method contains a parameter to grab the specific concreteBuilder object to produce the product. Further the director class then calls the concreteBuilder methods to create the product object in the correct order. When the process is completed, the builder class object’s GetResult() method may be used to return the product.

In simple words, the Builder provides an interface to create the components of a product class and ConcreteBuilder class implements this interface. The ConcreteBuilder class monitors the representation it produces, opens the way to acquire both the product and the construction of the product. The Director class builds the object via the Builder interface. The generated product is the object, usually complicated, we build.

3.1 Real Life Example

Before implementing the Builder design pattern in java code, let us look at a real life example to better understand this design pattern. To understand, consider an example of food ordering at restaurant. In the below diagram we will explain Builder design pattern using this real world example for better understanding.

Java Builder Design Pattern Example - UML Class Diagram
UML Class Diagram – Builder Pattern

In the above example of food ordering customer is acting as a client class, cashier acting as a director class and restaurant crew are acting as a builder class.  In the restaurant there are two types of meals are available such as veg meal and non veg meal. Veg meal consists of veg burger, fries, coke and toy car whereas Non veg meal consists of non veg pizza, fries, Pepsi and toy bike. Construction process for both the meal are same and it consists of five steps such as main item, side item, drink, toy and then pack. If suppose a customer went to the restaurant and orders a veg kid meal to the cashier. Cashier then forwards the order to the restaurant crew to complete the order. Now, restaurant crew first build the veg burger then they will build fries then coke and at last they build toy. After building all the meal restaurant crew now will pack the meal and forwards to the customer. So, here in this example veg kids meal is a complex object.

4. Implementing Builder design pattern

In this section, we will implement the Builder design pattern in java program using the real word example-Juice maker store. In Juice maker store the shopkeeper makes different types of fruit and vegetable juices according to customer’s order. Suppose if a customer orders an orange juice then the shopkeeper takes three or four oranges, water, sugar, ice cubes etc. as an ingredients and grinds all these ingredients in a juicer and serve to the customer.

Juice.java

public class Juice {

    private int water;
    private int fruit;
    private int sugar;
    private int icecube;
    private String juicename;

    public int getWater() {
        return water;
    }

    public void setWater(int water) {
        this.water = water;
    }

    public int getFruit() {
        return fruit;
    }

    public void setFruit(int fruit) {
        this.fruit = fruit;
    }

    public int getSugar() {
        return sugar;
    }

    public void setSugar(int sugar) {
        this.sugar = sugar;
    }

    public int getIceCube() {
        return icecube;
    }

    public void setIceCube(int icecube) {
        this.icecube= icecube;
    }

    public String getJuiceName() {
        return juicename;
    }

    public void setJuiceName(String juicename) {
        this.juicename= juicename;
    }

    public String toString() {
        return "Cold" + juicename + "!!!!  [" + water + " ml of water, " + fruit + "as a fruit, " + sugar +
            " gm of sugar, " + icecube + " ml of " + juicename + "]\n";
    }

}

In this above code we have created Juice class in which we have declared five private variables namely water, fruit, sugar, icecube, juicename. Also we have implemented set() and get() methods for this variables. For example, getwater() and setWater() methods.

JuiceMaker.java

public abstract class JuiceMaker {

    private Juice juice;

    public Juice getJuice() {
        return juice;
    }

    public void setJuice(Juice juice) {
        this.juice = juice;
    }

    public final Juice makeJuice() {
        Juice juice = createJuice();
        setJuice(juice);
        setJuiceType();
        setWater();
        setFruit();
        setSugar();
        setIceCube();
        return juice;
    }

    abstract void setJuiceType();

    abstract void setWater();

    abstract void setFruit();

    abstract void setSugar();

    abstract void setIceCube();

    abstract Juice createJuice();

}

In the above code we have created an abstract class known as JuiceMaker. In this abstract class we have declared Juice class variable as juice and implemented set() and get() methods for this variable. Also we have created template method that creates Juice object and returns Juice and we have defined several abstract methods such as setJuiceName(), setWater(), setFruit(), setSugar(), setIceCube(), createJuice().

OrangeJuice.java

public class OrangeJuice extends JuiceMaker {
    Juice createJuice() {
        return new Juice();
    }

    public void setWater() {
        System.out.println("Step 1 : Adding water into the juicer");
        getJuice().setWater(40);
    }

    public void setFruit() {
        System.out.println("Step 2 : Adding fruit into the juicer");
        getJuice().setFruit(4);
    }

    void setSugar() {
        System.out.println("Step 3 : Adding sugar into the juicer");
        getJuice().setSugar(10);
    }

    void setIceCube() {
        System.out.println("Step 4 : Adding 5 to 6 numbers of ice cubes into the juicer");
        getJuice().setIceCube(6);
    }

    void setJuiceType() {
        System.out.println("orange");
        getJuice().setJuiceName("orange");
    }

}

In the above code we have created OrangeJuice class which extends JuiceMaker abstract class. In this class we implemented the abstract classes that are defined in the JuiceMaker class. For example, setWater(), setFruit(), setSugar(), setIceCube(), setJuiceType().

AppleJuice.java

public class AppleJuice extends JuiceMaker {
    Juice createJuice() {
        return new Juice();
    }

    public void setWater() {
        System.out.println("Step 1 : Adding water into the juicer");
        getJuice().setWater(50);
    }

    public void setFruit() {
        System.out.println("Step 2 : Adding fruit into the juicer");
        getJuice().setFruit(6);
    }

    void setSugar() {
        System.out.println("Step 3 : Adding sugar into the juicer");
        getJuice().setSugar(20);
    }

    void setIceCube() {
        System.out.println("Step 4 : Adding 7 to 8 numbers of ice cubes into the juicer");
        getJuice().setIceCube(8);
    }

    void setJuiceType() {
        System.out.println("apple");
        getJuice().setJuiceName("apple");
    }

}

In the above code we have created AppleJuice class which extends JuiceMaker abstract class. In this class we implemented the abstract classes that are defined in the JuiceMaker class. For example, setWater(), setFruit(), setSugar(), setIceCube(), setJuiceType().

ShopKeeper.java

public class ShopKeeper {

    public static Juice takeOrder(String juiceType) {

        JuiceMaker juiceMaker = null;

        if (juiceType.equalsIgnoreCase("orange")) {
            juiceMaker = new OrangeJuice();
        } else if (juiceType.equalsIgnoreCase("apple")) {
            juiceMaker = new AppleJuice();
        } else {
            System.out.println("Sorry we don't take order for  " + juiceType);
        }
        return juiceMaker.makeJuice();
    }

}

In the above code we have created Shopkeeper class in which we have implemented takeOrder() method with one argument as juiceType. In this method we defined that if customer orders orange juice then the shopkeeper will make orange juice. Similarly for apple juice order.

BuilderDesignPattern.java

public class BuilderDesignPattern {
    public static void main(String[] args) {

        Juice orange = ShopKeeper.takeOrder("orange");
        System.out.println(orange);

        Juice apple = ShopKeeper.takeOrder("apple");
        System.out.println(apple);
    }
}

In the above code we have created BuilderDesignPattern class in which we have implemented main() method. Inside this main() method we have created Juice class object such as orange and apple and called takeOrder() method of Shopkeeper class.

5. Benefits of using Builder Design Pattern

In this article, already we have studied what the Builder design pattern is, its practical application using the java code, and also the understanding of the Builder design pattern class diagram and its real-world example. Now let’s start talking about its advantages.

  • Main benefit of Builder design pattern is that it enables to decrease the number of parameters in the constructor, so that optional parameters do not need to be passed to the constructor.
  • In this pattern the parameters for the constructor are limited and beautifully written method calls are offered.
  • One of the main advantage of this pattern is object has always been fully instantiated.
  • In this design pattern unchangeable objects can be constructed without too much complicated reasoning in the process of object construction.

6. Use of Builder Design Pattern

There are three common circumstances during which the Builder design pattern applies as follows:

  • Builder design pattern is applicable when we have a “telescopic” constructor. The Builder pattern allows us to create objects gradually. In addition, we can always use the necessary steps and avoid the optional steps when we build a single object.
  • Builder design pattern will be used to build totally different products using the same construction process. Each and every product is described by a separate constructor class. Building order control code can live in a single director class.
  • Step by step, Builder design pattern builds products. This empowers deferred or indeed recursive construction, which is required when you work with tree structures. During construction steps, Builder doesn’t really reveal incomplete products. So This precludes corrupt results from client code.

7. Demerits of Builder Design Pattern

So in this segment we will understand some of the downsides of the Builder design pattern:

  • The number of lines of program rises by at least double in the Builder design pattern, but in terms of design flexibility and so much more legible code the amount of effort pays off.
  • Another disadvantage of Builder design pattern is it requires the creation of an independent ConcreteBuilder for each and every product type.

8. Java Builder Design Pattern – Conclusion

Thus it is concluded that the Builder design pattern is a nice solution, not just for model classes, but to every object with over three or four parameters. We can increase readability of our code with a bit of additional work. Design patterns are hailed as the best in practical terms, so that’s a great advantage if we understand most of them and Builder design pattern is a good to start with.

9. Download the Source Code

The above implemented java program can be downloaded from the below link.

Download
You can download the full source code of this example here: BuilderDesignPattern.zip

Abhishek Kothari

Abhishek is a Web Developer with diverse skills across multiple Web development technologies. During his professional career, he has worked on numerous enterprise level applications and understood the technological architecture and complexities involved in making an exceptional project. His passion to share knowledge among the community through various mediums has led him towards being a Professional Online Trainer, Youtuber as well as Technical Content Writer.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button