Design pattern

Tram Ho

Builder

1. Ideas

Builder is a creative design template that allows you to build complex objects step by step. Templates allow you to create different styles and avatars of an object using the same build code.

2. Place the problem

Imagine a complex object that requires a lot of work, the step-by-step instantiation of multiple fields and nested objects. Such initialization code is usually buried inside a giant constructor with lots of parameters. Or even worse: scattered across the entire customer code.

For example, think about how to create a House object. To build a simple house, you need to build four walls and one floor, install doors, install a pair of windows and build a roof. But what if you want a bigger, brighter home with a backyard and other amenities (like heating, plumbing and wiring)?

The simplest solution is to extend the base House class and create a set of subclasses to include all combinations of parameters. But in the end you will end up with a significant number of subclasses. Any new parameters, such as porch type, will require further development of this hierarchy.

There is another approach that does not involve breeding of subclasses. You could create a giant constructor right in the base House class with all the possible parameters to control the House object. While this approach actually eliminates the need for subclasses, it creates another problem.

In most cases, most parameters will go unused, making the constructor calls pretty bad. For example, only a small fraction of the houses have swimming pools, so the parameters associated with the pool will be useless nine times out of ten.

3. Solution

The Builder pattern suggests that you extract the object building code out of its own class and move it to separate objects called the generator.

Some construction steps may require different implementation when you need to build different product avatars. For example, the wall of a cabin may be built of wood, but the castle walls must be made of stone.

In this case, you could create several different builder classes that implement the same set of build steps, but in a different way. You can then use these builders during the build (i.e. a set of calls to build steps) to create different types of objects.

For example, imagine one person builds everything from wood and glass, the second person builds everything out of stone and iron, and the third uses gold and diamonds. By calling the same group of steps, you get a regular house from the first builder, a small castle from the second, and a palace from the third. However, this will only work if the client code that calls the build steps can interact with the builders using the generic interface.

4. Instructions

You can go further and extract a series of calls to the builder steps you use to build the product into a separate class called director. The derector class determines the order in which the construction steps are performed, while the builder provides the implementation for those steps.

Having a director class in your program isn’t absolutely necessary. You can always call building steps in a specific order directly from the client code. However, the superintendent class can be a good place to put different construction processes in place so you can reuse them in your program.

In addition, the manager class completely hides the product’s structural details with the customer code. Customers just need to link the builder with the director, launch the project with the manager and get results from the builder.

5. Structure

6. Fake code

This example Builder template illustrates how you can reuse the same object building code when building different types of products, such as cars, and create corresponding manuals for them.

A car is a complex object that can be constructed in hundreds of different ways. Instead of extending the Vehicle class with a giant constructor, we extract the vehicle assembly code into a separate vehicle building class. This class has a set of methods for configuring various car parts.

If the customer code needs to assemble a specially tuned, special model of the car, the code can work directly with the manufacturer. On the other hand, the customer can delegate the assembly to the manager class, which knows how to use the builder to create some of the most popular car models.

You might get shocked, but every car needs manuals (seriously, who read them?). The manual describes every feature of the car, so the details in the manual will be different on different models. That is why you should reuse existing construction processes for both real cars and their respective manuals. Of course, building a manual is not the same as building a car and that’s why we have to provide another class of builders that specialize in crafting manuals. This class implements the same construction methods as its car-making cousin, but instead of fabricating auto parts, it describes them. By passing these builders to the same Director object, we can build a car or a manual.

The last part is fetching the result object. A metal car and a paper notebook, although related, are very different things. We cannot put a method to fetch results in director without associating director with product specific classes. Consequently, we get construction results from the builder who did the work.

7. Apply

  1. Make sure that you can clearly define the general build steps for building all available product demonstrations. Otherwise, you will not be able to continue implementing the template.
  2. Declare these steps in the base generator interface.
  3. Create a concrete builder class for each product rep and perform their construction steps.Don’t forget to implement a method to fetch the results of the build. The reason why this method cannot be declared inside the generator interface is because different builders can create products that do not have the same interface. Hence, you don’t know what the return type would be for such a method. However, if you are dealing with products from a hierarchy, then the fetch method can be safely added to the base interface.
  4. Think about creating a director class. It can include many different ways to build a product using the same constructor object.
  5. The client code creates both the generator and director objects. Before construction begins, the client must pass a builder object to the director. Typically, the client only does this once, through the parameters of the director’s constructor. Directors use the builder object in all other constructions. There is an alternative approach in which the builder is directed directly to the director’s construction method.
  6. Building results can only be obtained directly from the manager if all products follow the same interface. If not, the client fetches the results from the generator.

Reference link: https://refactoring.guru/design-patterns/builder

Share the news now

Source : Viblo