Design mode for java learning - Builder mode

Builder pattern

Summary

Separating the construction of a complex object from its representation allows the same construction process to create different representations.

  • Separate the components for construction (Builder responsible) and assembly (Director responsible). Thus complex objects can be constructed. This pattern applies when the construction of an object is complex.
  • Because decoupling of construction and assembly is implemented. Different builders, the same assembly, can also make different objects; The same builder, different assembly sequences can make different objects. That is to say, decoupling of the construction algorithm and the assembly algorithm is realized, and better reuse is achieved.
  • Builder mode separates parts from their assembly process to create a complex object step by step. Users only need to specify the type of a complex object to get it without knowing the details of its internal construction.

structure

The Builder model includes the following roles:

  • Abstract Builder Class: This interface specifies that the creation of those parts of a complex object is accomplished and does not involve the creation of specific part objects.
  • ConcreteBuilder: Implements the Builder interface to complete the specific creation of components of a complex product. After the construction process is complete, provide an instance of the product.
  • Product class: Complex object to be created.
  • Commander class (Director): Calls a specific builder to create parts of a complex object, with no specific product information involved in the instructor, and is responsible for ensuring that the parts of the object are created completely or in some order.

The class diagram is as follows:

Example

Create a shared bike
The production of bicycles is a complex process, which includes the production of frame, seat and other components. And the frame has carbon fiber, aluminum alloy and other materials
Yes, the car seat is made of rubber, leather and other materials. Builder mode is available for bicycle production. Here Bike is the product, which contains such components as frame, seat, etc. Builder is an abstract builder, MobikeBuilder and OfoBuilder are concrete builders; Director is the commander. The class diagram is as follows:

The code is as follows:

//Bicycles
public class Bike {
private String frame;
private String seat;
public String getFrame() {
return frame;
}
public void setFrame(String frame) {
this.frame = frame;
}
public String getSeat() {
return seat;
}
public void setSeat(String seat) {
this.seat = seat;
}
}
// Abstract builder class
public abstract class Builder {
protected Bike mBike = new Bike();
public abstract void buildFrame();
public abstract void buildSeat();
public abstract Bike createBike();
}
//Moba Cycling Builder Class
public class MobikeBuilder extends Builder {
@Override
public void buildFrame() {
mBike.setFrame("Aluminum alloy frame");
}
@Override
public void buildSeat() {
mBike.setSeat("Leather seat");
}
@Override
public Bike createBike() {
return mBike;
}
}
//ofo bicycle Builder class
public class OfoBuilder extends Builder {
@Override
public void buildFrame() {
mBike.setFrame("Carbon fiber frame");
}
@Override
public void buildSeat() {
mBike.setSeat("Rubber seat");
}
@Override
public Bike createBike() {
return mBike;
}
}
//Commander class
public class Director {
private Builder mBuilder;
public Director(Builder builder) {
mBuilder = builder;
}
public Bike construct() {
mBuilder.buildFrame();
mBuilder.buildSeat();
return mBuilder.createBike();
}
}
//Test Class
public class Client {
public static void main(String[] args) {
showBike(new OfoBuilder());
showBike(new MobikeBuilder());
}
private static void showBike(Builder builder) {
Director director = new Director(builder);
Bike bike = director.construct();
System.out.println(bike.getFrame());
System.out.println(bike.getSeat());
}
}

Be careful:
The example above is a general use of the Builder pattern, and the Commander class Director plays an important role in the Builder pattern.
Used to guide specific builders on how to build products, control the order of calls, and return complete product classes to callers, but there are some cases
The next step is to simplify the system structure by combining commander classes with abstract builders

//Abstract builder class
public abstract class Builder {
protected Bike mBike = new Bike();
public abstract void buildFrame();
public abstract void buildSeat();
public abstract Bike createBike();
public Bike construct() {
this.buildFrame();
this.BuildSeat();
return this.createBike();
}
}

Explain:
Doing so does simplify the system structure, but it also increases the responsibility of the abstract builder class, which is not too in line with the single responsibility principle, if
The construct() is too complex and is recommended to be encapsulated in the Director.

Advantages and disadvantages

Advantage:

  • Builder mode is very encapsulated. Builder mode is an effective way to encapsulate changes. In scenarios using builder mode, the general product class and builder class are more stable, so encapsulating the main business logic in the commander class as a whole can achieve better stability.
  • 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 creation process so that the same creation process can create different product objects.
  • You can control the process of creating a product more finely. Decomposition the creation steps of complex products into different methods makes the creation process clearer and easier to use programs to control the creation process.
  • Builder mode is easy to expand. If there is a new requirement, it can be accomplished by implementing a new builder class, basically not
    With code that has been tested and passed before the modification, there is no risk of introducing functionality. It conforms to the open and close principle.

Disadvantages:
Builder modes generally create products that have more in common and have similar components. Builder modes are not suitable for use if the differences between products are large, so their use is limited.

Use scenarios

Builder models create complex objects, and parts of their products often face dramatic changes, but the algorithms that combine them are relatively stable, so they are often used in the following situations.

  • The objects created are complex and consist of multiple components, each of which is facing complex changes, but the construction order between components is stable.
  • The algorithm for creating a complex object is independent of its components and how it is assembled, that is, the building process and the final representation of the product are independent.

Pattern Extension

In addition to the above uses, a common way to use the Builder pattern in development is to use the Builder pattern for refactoring when a class constructor needs to pass in many parameters and create an instance of the class with poor readability and easy incorrectness.
The code before refactoring is as follows:

public class Phone {
private String cpu;
private String screen;
private String memory;
private String mainboard;
public Phone(String cpu, String screen, String memory, String
mainboard) {
this.cpu = cpu;
this.screen = screen;
this.memory = memory;
this.mainboard = mainboard;
}
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getScreen() {
return screen;
}
public void setScreen(String screen) {
this.screen = screen;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public String getMainboard() {
return mainboard;
}
public void setMainboard(String mainboard) {
this.mainboard = mainboard;
}
@Override
public String toString() {
return "Phone{" +
"cpu='" + cpu + '\'' +
", screen='" + screen + '\'' +
", memory='" + memory + '\'' +
", mainboard='" + mainboard + '\'' +
'}';
}
}
public class Client {
public static void main(String[] args) {
//Build Phone Object
Phone phone = new Phone("intel","Samsung screen","Kingston","Asus");
System.out.println(phone);
}
}

The Phone object built in the client code above passes four parameters, what if it has more? Code readability and cost of use are high.
Refactoring the code after:

public class Phone {
private String cpu;
private String screen;
private String memory;
private String mainboard;
private Phone(Builder builder) {
cpu = builder.cpu;
screen = builder.screen;
memory = builder.memory;
mainboard = builder.mainboard;
}
public static final class Builder {
private String cpu;
private String screen;
private String memory;
private String mainboard;
public Builder() {}
public Builder cpu(String val) {
cpu = val;
return this;
}
public Builder screen(String val) {
screen = val;
return this;
public Builder memory(String val) {
memory = val;
return this;
}
public Builder mainboard(String val) {
mainboard = val;
return this;
}
public Phone build() {
return new Phone(this);}
}
@Override
public String toString() {
return "Phone{" +
"cpu='" + cpu + '\'' +
", screen='" + screen + '\'' +
", memory='" + memory + '\'' +
", mainboard='" + mainboard + '\'' +
'}';
}
}
public class Client {
public static void main(String[] args) {
Phone phone = new Phone.Builder()
.cpu("intel")
.mainboard("Asus")
.memory("Kingston")
.screen("Samsung")
.build();
System.out.println(phone);
}
}
}


Refactored code is more convenient to use and, to some extent, more efficient to develop. From the software design, the requirements for programmers are relatively high.

Tags: Java Design Pattern

Posted by konn on Fri, 19 Aug 2022 23:29:58 +0300