Builder Pattern [4 / 23]

Posted by newb110508 on Thu, 10 Mar 2022 02:23:24 +0100

4. Builder Pattern

catalogue

  • Builder pattern
    • Model motivation
    • Pattern definition
    • Pattern structure
    • Sequence diagram
    • code analysis
    • pattern analysis
    • example
    • advantage
    • shortcoming
    • Applicable environment
    • Mode application
    • Mode extension
    • summary

4.1. Model motivation

There are many components in the real world, such as the wheel, the steering wheel and so on. For most users, they don't need to know the assembly details of these parts, and hardly use a single part. Instead, they use a complete car, which can be designed and described through the builder mode. The builder mode can separate the parts from their assembly process and create a complex object step by step. Users only need to specify the type of complex object to get the object without knowing its internal specific construction details.

Separating a complex build from its representation allows the same build process to create different representations.

They are members of a series of complex object development types, and some of them have a large number of similar attributes. Moreover, there may be some restrictions in these complex objects. For example, if some attributes are not assigned, the complex object cannot be used as a complete product; Some attributes must be assigned in a certain order. Before one attribute is assigned, another attribute may not be assigned.

A complex object is equivalent to a car to be built, and the attributes of the object are equivalent to the parts of the car. The process of building a product is equivalent to the process of combining parts. Because the process of combining components is very complex, the combination process of these components is often "externalized" into an object called the builder. What the builder returns to the client is a completed product object, and the user does not need to care about the attributes contained in the object and their assembly method. This is the pattern motivation of the builder pattern.

The main solution is that in software systems, sometimes we are faced with the creation of "a complex object", which is usually composed of sub objects of each part with a certain algorithm; Due to the change of requirements, each part of this complex object often faces drastic changes, but the algorithm that combines them is relatively stable.

4.2. Pattern definition

Builder pattern: separate the construction of a complex object from its representation, so that the same construction process can create different representations.

Builder mode is to create a complex object step by step. It allows users to build complex objects only by specifying their types and contents. Users do not need to know the specific internal construction details. The builder mode belongs to the object creation mode. According to different Chinese translations, builder mode can also be called generator mode.

Builder Pattern uses multiple simple objects to build a complex object step by step. This type of design pattern is a creation pattern, which provides the best way to create objects.

A Builder class will construct the final object step by step. The Builder class is independent of other objects.

4.3. Pattern structure

The builder mode includes the following roles:

  • Builder: Abstract builder
  • ConcreteBuilder: specific builder
  • Director: Commander
  • Product: product role

Builder: create and provide instances,

Director: manage the dependencies of built instances.

4.4. Sequence diagram

4.5. code analysis

#include <iostream>
#include "ConcreteBuilder.h"
#include "Director.h"
#include "Builder.h"
#include "Product.h"

using namespace std;

int main(int argc, char *argv[])
{
	ConcreteBuilder * builder = new ConcreteBuilder();
	Director  director;
	director.setBuilder(builder);
	Product * pd =  director.constuct();
	pd->show();
	
	delete builder;
	delete pd;
	return 0;
}
///
//  ConcreteBuilder.cpp
//  Implementation of the Class ConcreteBuilder
//  Created on: 02-oct-2014 15:57:03
//  Original author: colin
///

#include "ConcreteBuilder.h"


ConcreteBuilder::ConcreteBuilder(){

}



ConcreteBuilder::~ConcreteBuilder(){

}

void ConcreteBuilder::buildPartA(){
	m_prod->setA("A Style "); //Different builders can realize the construction of different products  
}


void ConcreteBuilder::buildPartB(){
	m_prod->setB("B Style ");
}


void ConcreteBuilder::buildPartC(){
	m_prod->setC("C style ");
}
///
//  Director.cpp
//  Implementation of the Class Director
//  Created on: 02-oct-2014 15:57:01
//  Original author: colin
///

#include "Director.h"

Director::Director(){
}

Director::~Director(){
}

Product* Director::constuct(){
	m_pbuilder->buildPartA();
	m_pbuilder->buildPartB();
	m_pbuilder->buildPartC();
	
	return m_pbuilder->getResult();
}


void Director::setBuilder(Builder* buider){
	m_pbuilder = buider;
}

Operation results:

4.6. pattern analysis

The abstract builder class defines the creation method and return method of the product;

A Director class is also introduced into the structure of the builder mode. This class has two main functions: on the one hand, it isolates customers from the production process; On the other hand, it is responsible for controlling the product generation process. The commander programs for the abstract builder. The client only needs to know the type of the specific builder, and can call the relevant methods of the builder through the commander class to return a complete product object

In the client code, there is no need to care about the specific assembly process of product objects, just determine the type of specific builder. The builder mode separates the construction of complex objects from the performance of objects, so that the same construction process can create different performance.

4.7. example

Let's assume a business case of a fast food restaurant,

Among them, a typical set meal can be a Burger and a Cold drink.

Burger s can be veg burgers or chicken burgers, which are wrapped in cartons.

Cold drink s can be Coca Cola or pepsi, which are packed in bottles.

We will create an Item interface representing food items (such as hamburgers and cold drinks) and an entity class implementing the Item interface, as well as a Packing interface representing food packaging and an entity class implementing the Packing interface. Hamburgers are wrapped in cartons and cold drinks are packed in bottles.

Then we create a Meal class, ArrayList with Item and a MealBuilder that creates different types of Meal objects by combining items. BuilderPatternDemo, our demo class uses MealBuilder to create a Meal.

code:

//Create an interface that represents food items and food packaging.
public interface Item {
    public String name();
    public Packing packing();
    public float price();   
}
public interface Packing {
    public String pack();
}
//Create an entity class that implements the Packing interface.
public class Wrapper implements Packing {

    @Override
    public String pack() {
        return "Wrapper";
    }
}
public class Bottle implements Packing {

    @Override
    public String pack() {
        return "Bottle";
    }
}
//Create an abstract class that implements the Item interface, which provides default functions
public abstract class Burger implements Item {

    @Override
    public Packing packing() {
        return new Wrapper();
    }

    @Override
    public abstract float price();
}
public abstract class ColdDrink implements Item {

    @Override
    public Packing packing() {
        return new Bottle();
    }

    @Override
    public abstract float price();
}
//Create entity classes that extend Burger and coldsink.
public class VegBurger extends Burger {

    @Override
    public float price() {
        return 25.0f;
    }

    @Override
    public String name() {
        return "Veg Burger";
    }
}
public class ChickenBurger extends Burger {

    @Override
    public float price() {
        return 50.5f;
    }

    @Override
    public String name() {
        return "Chicken Burger";
    }
}
public class Coke extends ColdDrink {

    @Override
    public float price() {
        return 30.0f;
    }

    @Override
    public String name() {
        return "Coke";
    }
}
public class Pepsi extends ColdDrink {

    @Override
    public float price() {
        return 35.0f;
    }

    @Override
    public String name() {
        return "Pepsi";
    }
}
//Create a Meal class with the Item object defined above.
import java.util.ArrayList;
import java.util.List;

public class Meal {
    private List<Item> items = new ArrayList<Item>();  

    public void addItem(Item item){
        items.add(item);
    }

    public float getCost(){
        float cost = 0.0f;
        for (Item item : items) {
            cost += item.price();
        }      
        return cost;
    }

    public void showItems(){
        for (Item item : items) {
            System.out.print("Item : "+item.name());
            System.out.print(", Packing : "+item.packing().pack());
            System.out.println(", Price : "+item.price());
        }     
    }  
}
//Create a MealBuilder class, and the actual builder class is responsible for creating Meal objects.
public class MealBuilder {

    public Meal prepareVegMeal (){
        Meal meal = new Meal();
        meal.addItem(new VegBurger());
        meal.addItem(new Coke());
        return meal;
    }   

    public Meal prepareNonVegMeal (){
        Meal meal = new Meal();
        meal.addItem(new ChickenBurger());
        meal.addItem(new Pepsi());
        return meal;
    }
}
//BuiderPatternDemo uses MealBuider to demonstrate Builder Pattern 
public class BuilderPatternDemo {
    public static void main(String[] args) {
        MealBuilder mealBuilder = new MealBuilder();

        Meal vegMeal = mealBuilder.prepareVegMeal();
        System.out.println("Veg Meal");
        vegMeal.showItems();
        System.out.println("Total Cost: " +vegMeal.getCost());

        Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
        System.out.println("\n\nNon-Veg Meal");
        nonVegMeal.showItems();
        System.out.println("Total Cost: " +nonVegMeal.getCost());
    }
}
/*
output
Veg Meal
Item : Veg Burger, Packing : Wrapper, Price : 25.0
Item : Coke, Packing : Bottle, Price : 30.0
Total Cost: 55.0


Non-Veg Meal
Item : Chicken Burger, Packing : Wrapper, Price : 50.5
Item : Pepsi, Packing : Bottle, Price : 35.0
Total Cost: 85.5
*/

4.8. advantage

  • In the builder mode, the client does not need to know the details of the internal composition of the product, and decouples the product itself from the product creation process, so that the same creation process can create different product objects.
  • Each specific builder is relatively independent and has nothing to do with other specific builders. Therefore, it is convenient to replace or add new specific builders. Users can get different product objects by using different specific builders.
  • You can more finely control the product creation process. The creation steps of complex products are decomposed into different methods, which makes the creation process clearer and more convenient to use programs to control the creation process.
  • Adding a new specific builder does not need to modify the code of the original class library. The commander class is programmed for the abstract builder class, which is convenient for system expansion and conforms to the "opening and closing principle".

4.9. shortcoming

  • The products created by the builder mode generally have more in common and their components are similar. If there are great differences between products, it is not suitable to use the builder mode, so its scope of use is limited.
  • If the internal changes of the product are complex, it may lead to the need to define many specific builder classes to realize this change, resulting in a huge system.

4.10. Applicable environment

Builder mode can be used in the following cases:

  • The product objects that need to be generated have complex internal structures. These product objects usually contain multiple member attributes.
  • The attributes of the product objects to be generated depend on each other, and the generation order needs to be specified.
  • The creation process of an object is independent of the class that created the object. The commander class is introduced into the builder mode, and the creation process is encapsulated in the commander class, not in the builder class.
  • Isolate the creation and use of complex objects and enable the same creation process to create different products.

Some basic components do not change, but their combination often changes.

4.11. Mode application

In many game software, maps include sky, ground, background and other components, and personas include human body, clothing, equipment and other components. You can use the builder mode to design them, and create different types of maps or characters through different specific builders.

1. Go to KFC, hamburger, coke, French fries, fried chicken wings, etc. are unchanged, and their combination is often changed to produce the so-called "set meal".

2. StringBuilder in JAVA.

4.12. Mode extension

Simplification of builder mode:

  • Omit the role of abstract Builder: if only one concrete builder is required in the system, the abstract builder can be omitted.
  • Omit the commander role: when there is only one specific builder, if the abstract builder role has been omitted, you can also omit the commander role to make

Builder plays the dual roles of commander and builder.

Comparison between builder mode and abstract factory mode:

  • Compared with the abstract factory pattern, the builder pattern returns an assembled complete product, while the abstract factory pattern returns a series of related products, which are located in different product hierarchy and form a product family.
  • In the abstract factory mode, the client is an instance of the chemical plant class, and then the factory method is used to get the desired product object. In the builder mode, the client can not directly call the builder's related methods, but through the command class to guide how to generate objects, including the assembly process and the construction steps of the image, and it focuses on constructing a complex object step by step. Returns a complete object.
  • If the abstract factory model is regarded as an auto parts production factory to produce the products of a product family, the builder model is an auto assembly factory, which can return a complete car through the assembly of parts.

The difference from the factory mode is that the builder mode pays more attention to the assembly sequence of parts.

4.13. summary

  • The builder pattern separates the construction of a complex object from its representation, so that the same construction process can create different representations. Builder mode is to create a complex object step by step. It allows users to build complex objects only by specifying their types and contents. Users do not need to know the specific internal construction details. The builder mode belongs to the object creation mode.
  • The builder pattern includes the following four roles: the abstract builder specifies the abstract interface for each part of creating a product object; The concrete builder implements the abstract builder interface, realizes the construction and assembly methods of various components, defines and defines the complex objects it creates, and can also provide a method to return the created complex product objects; Product role is a complex object constructed, which contains multiple components; The commanders are responsible for arranging the order of complex objects. There is an association between the commanders and the abstract builders. In the construct() construction method, the components and the assembly methods of the builder's objects can be invoked to complete the construction of complex objects.
  • A director class is introduced into the structure of the builder model. This class has two main functions: on the one hand, it separates the customer from the production process; On the other hand, it is responsible for controlling the product generation process. The commander programs for the abstract builder. The client only needs to know the type of the specific builder, and can call the relevant methods of the builder through the commander class to return a complete product object.
  • The main advantage of the builder mode is that the client does not need to know the details of the internal composition of the product, and decouples the product itself from the product creation process, so that the same creation process can create different product objects. Each specific builder is relatively independent and has nothing to do with other specific builders, Therefore, it is convenient to replace specific builders or add new specific builders, which conforms to the "opening and closing principle", and can also more finely control the product creation process; The main disadvantage is that the products created by the builder mode generally have more in common and their components are similar, so their scope of use is limited. If the internal changes of the product are complex, it may lead to the need to define many specific builder classes to realize this change, resulting in the huge system.
  • The application of builder mode includes: the product objects to be generated have complex internal structure, and these product objects usually contain multiple member attributes; The attributes of the product objects to be generated depend on each other, and the generation order needs to be specified; The creation process of an object is independent of the class that created the object; Isolate the creation and use of complex objects, and enable the same creation process to create different types of products.

Topics: Design Pattern Back-end