top

Search

Software Key Tutorial

.

UpGrad

Software Key Tutorial

Builder Design Pattern

Introduction

The Builder Design Pattern is a well-established software design pattern that belongs to the category of creational patterns. It provides a solution to the problem known as the telescoping constructor anti-pattern. The Builder Design Pattern is an excellent choice when creating an object becomes complex due to a large number of parameters or when the object construction process should allow different representations for the object being built.

However, it is important to note that the Builder Design Pattern does not eliminate the necessity of using setters or constructors. Instead, it offers a more refined and controlled method for constructing intricate objects.

Overview

In your journey of mastering design patterns, you will find that the Builder Design Pattern is the one that offers flexibility during object creation. It comes into play when an object needs to be created step by step, and each stage is mandatory. This pattern assists in constructing a complex object, thus creating an easy way to write readable and maintainable code.

What is the Builder Design Pattern?

The Builder Design Pattern, a part of the Gang of Four's creational layout pattern, separates the development of an item from its representation. It's useful when the algorithm for developing a complex item is independent of the components that make up the object and how they're assembled. 

Consider, for instance, the procedure for creating a pizza. You have various components, such as the crust, sauce, toppings, and cheese. Depending on the sort of pizza you need, these constituents may alternate, or their assembly may vary. The Builder Design Pattern will make certain that the procedure of creating any type of pizza is uniform and systematic, and it is only the elements and their assembly that get adjusted.

UML Diagram of Builder Design Pattern

In a UML diagram, the Builder Design Pattern generally includes: 

  • A Builder interface that specifies methods for creating the parts of a product

  • A ConcreteBuilder that constructs and assembles parts to build the products

  • A Director that constructs an object using the Builder interface

  • A Product that represents the complex object under construction

This image shows that the ConcreteBuilder is responsible for implementing the Builder interface and constructing the product. The Director uses the methods of the ConcreteBuilder to construct the object.

Example of Builder Design Pattern

Let's take a concrete builder design pattern example to understand it better. Suppose we have a CD manufacturing company that serves different firms like Sony and Samsung. The CD production for both establishments involves a similar step-by-step process, but the end product varies based on each one’s specifications.

Create Packing Interface

Firstly, we define a `Packing` interface that is implemented by the `CD` class, which acts as the product in this context.

Create Abstract Classes, CD and Company

Then we create two abstract classes: `CD`, which implements `Packing`, and `Company`, which extends `CD`. `CD` provides the default functionalities for packing and pricing, whereas `Company` requires the `pack()` method to be implemented.

Create Implementation Classes of Company, Sony and Samsung

Now, we create `Sony` and `Samsung` classes, which are concrete implementations of the `Company` class. They override the `pack()` and `price()` methods to provide company-specific details.

Create the CDType Class

Next, we create the `CDType` class, which uses the Builder to construct the `CD`.

Create the CDBuilder Class

We create the `CDBuilder` class, which will be used to build `CDType` objects.

Create the BuilderDemo Class

Finally, we test our builder in `BuilderDemo` class.

In this example, the Builder (`CDBuilder`) constructs a `CDType` using the `Company` class (`Sony` and `Samsung`). The `BuilderDemo` (Director) uses the `CDBuilder` to create a `CDType`.

Let's break down the code snippet and understand how it employs the Builder Design Pattern.

### CDBuilder: Builder Class

The builder `CDBuilder` helps produce a `CDType` object. It has methods like `buildSonyCD()` and `buildSamsungCD()` for creating CD objects for certain firms. These methods specify CD properties like company, type, price, etc., encapsulating creation logic.

### Director Class: BuilderDemo

BuilderDemo is the director. The `main` method in `BuilderDemo` controls the creation, utilizing `CDBuilder` to generate Sony and Samsung-specific `CDType` objects.

A Detailed Description of Code

1. A `CDBuilder` class instance is generated in the first step. This builder object has methods for making CDs for different companies.

2. To build a Sony CD, The `buildSonyCD()` method is invoked on the `cdBuilder` object. This method creates a Sony CD by setting the type, adding music, and pricing. Finally, a `CDType` object representing the Sony CD is returned.

3. Samsung CD creation: The `buildSamsungCD()` method on the `cdBuilder` object creates a Samsung CD with Samsung-specific properties, following the Sony CD pattern.

4. Displaying Items: The `showItems()` method displays CD data on both `cdType1` and `cdType2`. This displays the built objects and verifies the builder's work.

5. Encapsulation and Flexibility: The builder abstracts construction logic for easy adjustments. Adding additional CD types or changing building details requires only modifying the `CDBuilder` class, leaving the client code (`BuilderDemo`) unchanged.

The entire process shows decoupling, so the client code doesn't need to know object creation details. Instead, it gives the builder this duty, increasing code reuse and maintainability.

The output of the above code will be:

This signifies that we have successfully created Sony and Samsung CDs with their respective details.

When Will We Need Builder Design Pattern?

The Builder Design Pattern is particularly useful when the object creation involves several steps, and these steps need to be kept separate from the main business logic. For instance, if you're developing a Document Creator system that needs to generate various types of documents (PDF, Word, Excel), each having a different construction process, you might consider employing the Builder Design Pattern. It allows the same construction process to create different types of objects.

How Does Builder Design Pattern Work?

In the Builder Design Pattern, each step in the construction process is represented by a method in the Builder interface. The Builder implementation specifies how each step in the construction process is executed, resulting in different kinds of objects. A Director controls the construction order, invoking the Builder's steps.

To elaborate further, the Director asks the Builder to perform steps 1,  2,  3, and so on, not worrying about what they do. This way, the same process can create different representations.

Pseudocode

The following pseudocode provides a high-level view of how the Builder Design Pattern might be structured.

Language Specific Code

Now, let's see how we can implement the Builder Design Pattern in different programming languages.

Java

In Java, we can take advantage of its strong typing and object-oriented features to create a robust implementation of the Builder Design Pattern.

  

C++

In C++, we use pointers and manual memory management. Here's an example of how you might implement the Builder Design Pattern in C++.

   

Python

In Python, we have dynamic typing and garbage collection, which leads to a different style of coding. Here's how you might implement the Builder Design Pattern in Python.

Output

This code does not have a direct visual output since there's no print statement or display method. However, after executing the code, the product object will have the following state:

  • product.partA: "PartA1"

  • product.partB: "PartB1"

Difference between Builder Design Pattern and Factory Design Pattern

While both the Factory and Builder Design Patterns are used for object creation, they serve different purposes. The Factory Design Pattern creates an object in a single step and is usually used when the designing is a one-step process. On the other hand, the Builder Design Pattern is used when the object creation involves multiple steps. 

For instance, a Factory Pattern can create a simple `User` object with a username and password. But you might find the Builder Pattern more suitable when you need to create a more complex `UserProfile` object that includes the user's preferences, settings, and security questions.

Advantages of Builder Design Pattern

1. Allows for step-by-step construction: The Builder Design Pattern provides a clear separation between the construction and representation of an object. This allows for greater control over the construction process.

2. Improves code readability: Using the builder, the client code can create objects with a clear, readable syntax, even when the objects are complex.

3. Creates different products with the same construction process: With the Builder Design Pattern, the same construction process can create different types of products.

Disadvantages of Builder Design Pattern

1. Creates complexity: The Builder Design Pattern isn't beneficial when the object can be created in a single step, as it may introduce unnecessary complexity.

2. Requires more lines of code: This pattern requires several new classes, which can increase the code length.

Builder Design Pattern in Practice

When applied to real-world circumstances, the Builder Design Pattern shines, delivering elegant answers to complicated challenges. Here are some examples of when it comes in handy:

GUI Builders

The Builder Pattern is used by Integrated Development Environments (IDEs) for their GUI builder tools. It simplifies step-by-step UI building by producing the relevant code visually as you design the UI.

SQL Query Generators

The Builder Pattern is useful when programming complex SQL queries. Instead of error-prone text concatenation, SQL query builders allow you to write queries logically, enhancing readability and security.

Game Character Development

The Builder Pattern in gaming software facilitates character building by providing means to set various traits such as strength, intellect, and agility. It improves code comprehension, making character diversity more manageable.

HTTP Clients and Requests

To generate requests, HTTP client libraries employ the Builder Pattern. You can increase code readability and maintainability by adding headers, configuring the body, and inserting query parameters step by step.

Document Conversion Services

The Builder Pattern aids in the conversion of documents from one format to another in document processing software. Different builders can be used for different formats, improving the final document's construction efficiency.

These examples demonstrate the Builder Design Pattern's utility, ability to handle complicated constructs while improving code clarity and speed.

Conclusion

The Builder Design Pattern is a reliable solution for creating complex objects. Employing a step-by-step approach to object construction effectively establishes a clear distinction between the construction and representation of an object. This separation greatly enhances the readability and maintainability of the code. However, it is important to remember that, similar to any design pattern, it should not be applied without careful consideration of its suitability for your specific use case.

FAQs

1. Do the Builder Design Pattern and Single Responsibility Principle relate to each other?

 The Single Responsibility Principle (SRP) requires classes to change for one cause. The Builder Design Pattern follows this rule and assures that each class has one responsibility by isolating creation logic from the item being produced. This separation strengthens the SRP by allowing construction process adjustments without affecting the product class and vice versa.

2. In what circumstances is the Builder Design Pattern ineffective? 

 The Builder Design Pattern is ineffective when the object creation process is straightforward and can be completed in a single phase or by using a constructor. Implementing this Pattern could add superfluous complexity to your code in such situations.

3. What is the purpose of the Builder Design Pattern's Director class? 

 The Builder Design Pattern's Director class controls the object construction procedure. It specifies the construction sequence and the build order. However, the director is optional for the builder pattern, and the client code can directly utilize the builder.

4. How does the Builder Design Pattern enhance the legibility of code?

By encapsulating the complex construction logic within a builder class, the Builder Design Pattern can substantially improve code readability. It provides methods for setting each parameter individually, making the client code more intuitive, understandable, and manageable. 

Leave a Reply

Your email address will not be published. Required fields are marked *