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 as much as possible, and try to clarify my understanding. The Builder Design Pattern is mainly studied from the following aspects, 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 to create complex objects. It abstracts the construction process of complex objects and assembles different objects through different implementations of builders and assemblers. It is very convenient to add different implementations of builders and assemblers without modifying the previous code.

Essence#

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

Key Concepts#

  • Builder: Builds different sub-components and returns 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: Builds related sub-components through a specific builder and provides methods to compose complex product objects.

When a complex object needs to be generated, the desired specific object can be obtained directly through a specific director. The user does not need to care about the assembly process and the 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 properties.

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;
	// omitted getter, setter, toString methods
	// ...
}

// 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 builderScreen();
	Camera builderCamera();
	Cpu builderCpu();
}

Concrete builder:

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

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

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

	@Override
	public Cpu builderCpu() {
		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.builderScreen());
		phone.setCamera(builder.builderCamera());
		phone.setCpu(builder.builderCpu());
		return phone;
	}
}

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

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 screen...
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, that is, a phone with a screen of Mi-screen, a camera of Mi-camera, and a CPU of Mi-cpu, through the specific director MiPhoneDirector.

Summary#

The Builder Design Pattern is generally used for complex objects with common characteristics. The object itself is separated from the construction and assembly processes, achieving configurable properties of complex objects. Of course, 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 use the Builder Design Pattern, making it convenient to configure some properties of complex objects.

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