banner
jzman

jzman

Coding、思考、自觉。
github

Builder design pattern

This is the second article in the Design Patterns series - Builder Design Pattern. I hope the articles I publish are a series, keeping the same writing style and making my understanding clear. The main aspects of learning about the Builder Design Pattern are as follows:

  1. Overview
  2. Essence
  3. Key Concepts
  4. Specific Implementation
  5. Summary

Overview#

The Builder Design Pattern belongs to the creational design patterns and is mainly used for creating complex objects. It abstracts the construction process of complex objects and assembles different objects through different implementations of builders and assemblers. It allows for easy addition of different implementations of builders and assemblers without modifying previous code.

Essence#

The Builder Design Pattern separates the construction process and assembly process of object sub-components, achieving decoupling of construction and assembly. Different builders with the same assembly order or the same builder with different assembly orders can create different objects, fully decoupling construction and assembly and achieving decoupling of construction and assembly algorithms, thus achieving better reusability.

Key Concepts#

  • Builder: Builds different sub-components and returns the sub-components or provides methods to obtain complex objects. It abstracts the construction process into an interface or abstract class, making it easy to extend specific builders.

  • Director: Uses a specific builder to construct related sub-components and provides methods to assemble the complex product object.

When a complex object needs to be generated, the desired specific object can be obtained directly through a specific director, without the need to be concerned about the assembly process and construction process, which are completed internally by the specific director and specific builder respectively. Of course, a complex object can be understood as an object with many attributes.

Specific Implementation#

The specific implementation of the Builder Design Pattern is illustrated below using the assembly process of a phone. The product class is as follows:

/**
 * Product
 */
public class Phone {
    private Screen screen;
    private Camera camera;
    private Cpu cpu;
    //...
}

// Sub-component
class Screen {
    private String name;
    //...
}

// Sub-component
class Camera {
    private String name;
    //...
}

// Sub-component
class Cpu {
    private String name;
    //...
}

Abstract builder:

/**
 * Builder
 */
public interface PhoneBuilder {
    Screen buildScreen();
    Camera buildCamera();
    Cpu buildCpu();
}

Concrete builder:

/**
 * Concrete builder
 */
public class MiPhoneBuilder implements PhoneBuilder {

    @Override
    public Screen buildScreen() {
        System.out.println("Building screen...");
        return new Screen("Mi-screen");
    }

    @Override
    public Camera buildCamera() {
        System.out.println("Building camera...");
        return new Camera("Mi-camera");
    }

    @Override
    public Cpu buildCpu() {
        System.out.println("Building CPU...");
        return new Cpu("Mi-cpu");
    }
}

Abstract director:

/**
 * Abstract director
 */
public interface PhoneDirector {
    Phone directPhone();
}

Concrete director:

/**
 * Concrete director
 */
public class MiPhoneDirector implements PhoneDirector {
    private PhoneBuilder builder;

    public MiPhoneDirector(PhoneBuilder builder) {
        this.builder = builder;
    }

    @Override
    public Phone directPhone() {
        Phone phone = new Phone();
        phone.setScreen(builder.buildScreen());
        phone.setCamera(builder.buildCamera());
        phone.setCpu(builder.buildCpu());
        return phone;
    }
}

The user directly obtains the final product through a specific director, as shown below:

public class Client {
    public static void main(String[] args) {
        PhoneBuilder builder = new MiPhoneBuilder();
        MiPhoneDirector director = new MiPhoneDirector(builder);
        Phone phone = director.directPhone();
        System.out.println(phone);
    }
}

The execution result is as follows:

Building screen...
Building camera...
Building CPU...
Phone [screen=Screen [name=Mi-screen], camera=Camera [name=Mi-camera], cpu=Cpu [name=Mi-cpu]]

Finally, the user assembles a phone with obvious assembly characteristics through the specific director MiPhoneDirector, which has a screen of Mi-screen, a camera of Mi-camera, and a CPU of Mi-cpu.

Summary#

The Builder Design Pattern is generally used for complex objects with common characteristics. It separates the object itself from the construction and assembly processes, allowing for configurable properties of complex objects. However, if the internal complexity of the complex object is too high, it will inevitably require the creation of more builder classes, making the construction process cumbersome. I think the use of the Builder Design Pattern in development is mainly for encapsulation, making the code more flexible. APIs like Picasso and Glide also use the Builder Design Pattern, making it convenient to configure certain properties of complex objects.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.