Builder pattern. Implementation in Java. Example
Before studying this topic, it is recommended that you familiarize yourself with the following topic:
Contents
- 1. The structure of the Builder pattern. Figure
- 2. An example of implementation of the Builder pattern in Java. Creating a complex number object
- 3. Using the Builder pattern for two specific builders. Java solution
- Related topics
Search other websites:
1. The structure of the Builder pattern. Figure
The Builder pattern is a generative pattern. The pattern is intended to produce objects. The structure of the Builder pattern is shown in Figure 1.
Figure 1. The structure of the Builder pattern. Generalized case
⇑
2. An example of implementation of the Builder pattern in Java. Creating a complex number object
2.1. The task. The picture to be implemented
The example demonstrates the implementation of the Builder pattern, which is based on the structure shown in Figure 2. The product is the Complex class, which defines a complex number consisting of a real and an imaginary part. In the Director class, the Construct() method constructs the two parts of the complex number. The resulting number is returned to the client in the GetResult() method.
Figure 2. The structure of the Builder pattern showing the solution of the problem
⇑
2.2. Program code for solving the problem
The implementation of the Builder pattern in Java is as follows
// Implementation of the Builder pattern in Java. // The class that is the product is a complex number class Complex { public double re; // real part of a complex number public double im; // imaginary part of a complex number } // A class that implements an interface with a client class Builder{ // Methods that are passed to the client void CreateComplex() {} void BuildPart1(int part1) {} void BuildPart2(int part2) {} Complex GetResult() { return null; } } // A class that is a concrete builder class ConcreteBuilder extends Builder { // Reference private Complex currentBuilder; // Constructor ConcreteBuilder() { currentBuilder = null; } // Overriding methods defined in the Builder class void CreateComplex() { System.out.println("ConcreteBuilder.CreateComplex()"); currentBuilder = new Complex(); } // Build part 1 void BuildPart1(int part1) { currentBuilder.re = part1; } // Build part 2 void BuildPart2(int part2) { currentBuilder.im = part2; } // Return a complex number for the client Complex GetResult() { return currentBuilder; } } // Class-disposer class Director { // Method constructing parts // gets a reference to the class that implements the interface with the client void Construct(Builder builder) { // Create a product builder.CreateComplex(); // Build part 1 builder.BuildPart1(15); // Build part 2 builder.BuildPart2(30); } } public class TestBuilder { public static void main(String[] args) { // The main() function acts as a client // 1. Declare complex number reference (product) Complex C; // 2. Create a concrete instance of the ConcreteBuilder class ConcreteBuilder B = new ConcreteBuilder(); // 3. Create a class-disposer and configure it with product B Director D = new Director(); D.Construct(B); // 4. Pass the created product to the client C = B.GetResult(); // 5. Print the value of a complex number (for verification) System.out.println("C.re = " + C.re); System.out.println("C.im = " + C.im); } }
⇑
2.3. Explanation to the solution
Let’s explain some code snippets. The result of the Builder pattern should be a class object. In our case, the result of the pattern operation is an object of the Complex class. Optionally, you can replace the Complex class as you see fit.
The Builder class is used to communicate with the client. This class has a GetResult() method that returns a constructed object of type Complex to the client. This is the result of the pattern.
The Director class declares one single Construct() method that creates an instance of the Builder class and builds its parts – the BuildPart1() and BuildPart2() methods. In our case, the parts are the real part of the complex number (the variable re of the Complex class) and the imaginary part of the complex number (the im variable of the Complex class). The Construct() method is called by the client to construct an object. Various variations are allowed here to obtain the desired object.
A concrete instance (object) of the Complex class is directly created in the ConcreteBuilder class and, through the mechanism of virtual functions (dynamic polymorphism), is returned to the client as a reference to the Builder class. Thanks to polymorphism and inheritance, you can add builder classes inherited from the Builder class (ConcreteBuilder2, ConcreteBuilder3, etc.) to the structure, which will build (create) various products.
⇑
2.4. The result of the program
After starting the program will give the following result
ConcreteBuilder.CreateComplex() C.re = 15.0 C.im = 30.0
⇑
3. Using the Builder pattern for two specific builders. Java solution
In the Builder pattern, the number of concrete builder classes (ConcreteBuilder) can be several. This example demonstrates the use of two specific builders.
3.1. Task
Using the structure of the Builder pattern, develop the construction of objects of the following classes:
- a class containing means for converting a string from binary to decimal;
- a class containing means for converting a string from octal to decimal.
The product of the classes is a convertible string (type String).
⇑
3.2. Block diagram of the problem solution
The first step in solving the problem is to build a structural diagram. In our case, the block diagram is shown in Figure 3.
Figure 3. Block diagram of the problem solution
As you can see from the diagram, the solution to the problem is based on the following classes:
- Builder – a class that implements an interface with a client;
- Director is the manager class. Contains a Construct() method that constructs an object of type Builder;
- Convert_2_to_10 – a class containing means for converting a string from binary to decimal;
- Convert_8_to_10 – a class containing means for converting a string from octal to decimal.
The program also uses the TestBuilder class, which contains a main() function that demonstrates how the client works.
⇑
3.3. The program code for solving the problem
In Java, the program code for solving the problem is as follows.
// Implementation of the Builder pattern in Java. // A class that implements an interface with a client interface Builder { void Convert(String str2); String GetResult(); } // Class containing means for converting numbers // from binary to decimal class Convert_2_to_10 implements Builder { private String str10; // Decimal number - converted number // Conversion method Convert () - gets a number as a string in binary system public void Convert(String str2) { // Need to convert str2 to str10 // 1. Check if str2 is correct, if not, then convert to an empty string for (int i=0; i<str2.length(); i++) if (!((str2.charAt(i)=='0') || (str2.charAt(i)=='1'))) { str10 = "Error. Incorrect value."; // string str2 contains an invalid character return; } // 2. Converting from binary string to decimal int power = 1; int number = 0; int pos; for (int i=0; i<str2.length(); i++) { // power with base 2 if (i==0) power = 1; else power = power*2; // position in string pos = str2.length()-i-1; // bits are added where character is 1 if (str2.charAt(pos) == '1') number = number + power; } // 3. Converting a decimal number to a decimal string str10 = ""; while (number>0) { str10 = (number%10) + str10; number = number / 10; } } public String GetResult() { return str10; } } // Class containing converters // from octal to decimal class Convert_8_to_10 implements Builder { private String str10; // result // Conversion method Convert () - gets a number as a string in octal public void Convert(String str8) { // Need to convert str8 to str10 // 1. Check if str8 is correct, if not, then convert to empty string for (int i=0; i<str8.length(); i++) if ((str8.charAt(i)<'0') || (str8.charAt(i)>'7')) { str10 = "Error. Incorrect value."; // string str2 contains an invalid character return; } // 2. Converting from an octal string to a decimal number int power = 1; int number = 0; int pos; for (int i=0; i<str8.length(); i++) { // power with base 8 if (i==0) power = 1; else power = power*8; // position in string pos = str8.length()-i-1; // formula for calculating the term number = number + (str8.charAt(pos)-'0')*power; } // 3. formula for calculating the addendum str10 = ""; while (number > 0) { str10 = (number % 10) + str10; number = number / 10; } } // Implementation of GetResult() method public String GetResult() { return str10; } } // Class-manager class Director { // Method constructing parts // gets a reference to the class that implements the interface with the client void Construct(Builder builder) { // Build a product for a client builder.Convert("100010"); } // Builds a class object for the octal number system void Construct2(Builder builder) { builder.Convert("770"); } } public class TestBuilder { public static void main(String[] args) { // The main () function acts as a client // 1. Constructing an object of class Convert_2_to_10 // 1.1. Create a specific instance of the Convert_2_to_10 class Convert_2_to_10 obj1 = new Convert_2_to_10(); // 1.2. Create a class-manager and configure it with the obj1 product Director D = new Director(); D.Construct(obj1); // 1.3. Get the result string and print it String res = obj1.GetResult(); System.out.println("res_2 = " + res); // ---------------------------------------------------------------- // 2. Constructing an object of class Convert_8_to_10 // 2.1. Create a specific instance of the Convert_8_to_10 class Builder obj2 = new Convert_8_to_10(); // You can create an instance like that // 2.2. Create a new instance D.Construct2(obj2); // 2.3. Return the constructed instance to the client String res2 = obj2.GetResult(); System.out.println("res_8 = " + res2); } }
As you can see from the code, the communication of concrete builder classes (Convert_2_to_10, Convert_8_to_10) with the client is carried out through the Builder interface and not through the class, as shown in the previous example. Using an interface instead of a class is shown for demonstration purposes.
According to the definition of the Builder pattern, methods in a class can do nothing. An interface or class can be replaced with an abstract class. All this is determined by the specifics of the task.
⇑
3.4. The result of the program
After running for execution, the program will give the following result
res_2 = 34 res_8 = 504
⇑
Related topics
- Builder pattern. Review and research. Implementation in C++
- Implementing the Builder pattern in C#. Examples
⇑