One introduction
explain : If you want to read the definition and other theoretical content directly , You can jump directly to the second largest point
There are a lot of scenes in life that we are going to talk about today “ Builder pattern ” It's a perfect match , For example, a computer is made up of CPU、 Memory 、 The graphics card 、 Memory 、 mouse 、 keyboard 、 Display and so on , We want a computer , We won't be able to make these accessories ourselves , It's usually done by telling the sales company , Then it sends production technicians to do the specified accessories for you .
I don't care , Who will buy it , Who does it , Who manages the problem , We can analyze and get , The one that builds computers “ The process ” It is stable. in other words , Whatever the configuration of the computer , These accessories are necessary , It's just The details are different , For example, your configuration is better , He's less than
however , I'm a buyer , I don't want to worry about that , I'll just tell you , I want a computer with medium configuration , You are responsible for “ build ” OK, just give it to me , This is the more popular way of saying the builder model
Here's an example of this computer , Take a look at it step by step :
Two Step by step through examples to understand the builder model
First , No matter how you build it , How to buy , One Computer Computer is a must , Let's randomly select three components to demonstrate ,CPU、 Memory 、 Monitor , To supplement get set toString Method
/**
* product : The computer
*/
public class Computer {
private String cpu; // CPU
private String graphicsCard; // Memory
private String displayScreen; // Monitor
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getGraphicsCard() {
return graphicsCard;
}
public void setGraphicsCard(String graphicsCard) {
this.graphicsCard = graphicsCard;
}
public String getDisplayScreen() {
return displayScreen;
}
public void setDisplayScreen(String displayScreen) {
this.displayScreen = displayScreen;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", graphicsCard='" + graphicsCard + '\'' +
", displayScreen='" + displayScreen + '\'' +
'}';
}
}
( One ) The simplest and most straightforward way ( Not good. )
This method basically has no technical content , direct new + set That's it
public class Test {
public static void main(String[] args) {
Computer computer = new Computer();
computer.setCpu(" Intel core i5 processor ");
computer.setGraphicsCard("4g Memory ");
computer.setDisplayScreen("14 " 1080p 60hz Monitor ");
System.out.println(computer.toString());
}
}
Print the results :
Computer{cpu=' Intel core i5 processor ', graphicsCard='4g', displayScreen='14 " 1080p 60hz Monitor '}
( Two ) Customers contact production technicians directly
This way up here , Needless to say, it's not appropriate , So the technicians ( builder ) Here he comes ! But different technicians will make different accessories , For example, some can do 144hz Display for , And some specialize in 60hz Display for , There are high and low configuration , Different models
So we abstracted a ComputerBuilder The abstract class of
/**
* The computer builder
*/
public abstract class ComputerBuilder {
abstract void buildCpu(); // build CPU
abstract void buildGraphicsCard(); // Building memory
abstract void buildDisplayScreen(); // Building displays
abstract Computer getComputer(); // Get this computer
}
Let's write about the specific builder , For example, first write an implementation of a low configuration computer
/**
* Low configuration computer
*/
public class LowConfigurationComputerBuilder extends ComputerBuilder {
private Computer computer;
public LowConfigurationComputerBuilder(){
computer = new Computer();
}
@Override
void buildCpu() {
computer.setCpu(" Intel core i5 processor ");
System.out.println("buildCpu: Intel core i5 processor ");
}
@Override
void buildGraphicsCard() {
computer.setGraphicsCard("8g Memory ");
System.out.println("buildGraphicsCard: 8g Memory ");
}
@Override
void buildDisplayScreen() {
computer.setDisplayScreen("1080p 60hz Monitor ");
System.out.println("buildDisplayScreen: 1080p 60hz Monitor ");
}
@Override
Computer getComputer() {
return computer;
}
}
Test it :
public class Test {
public static void main(String[] args) {
// Create a low configuration computer builder
LowConfigurationComputerBuilder builder = new LowConfigurationComputerBuilder();
builder.buildCpu();
builder.buildGraphicsCard();
builder.buildDisplayScreen();
Computer computer = builder.getComputer();
System.out.println(" Computers built : " + computer );
}
}
Execution results :
buildCpu: Intel core i5 processor
buildGraphicsCard: 8g Memory
buildDisplayScreen: 1080p 60hz Monitor
Computers built : Computer{cpu=' Intel core i5 processor ', graphicsCard='8g Memory ', displayScreen='1080p 60hz Monitor '}
( 3、 ... and ) Customers contact the sales company
Although the above method is better than the first one , But the customer goes to contact the production technician himself , Obviously not very reasonable , Normal practice , We all contact the sales company first , Just tell them what configuration I want , I don't care about the details
public class SalesCompany {
public Computer buildComputer(ComputerBuilder builder){
builder.buildCpu();
builder.buildGraphicsCard();
builder.buildDisplayScreen();
return builder.getComputer();
}
}
Test code
public class Test {
public static void main(String[] args) {
// Create a low configuration computer builder
LowConfigurationComputerBuilder builder = new LowConfigurationComputerBuilder();
// Create a computer sales center
SalesCompany salesCompany = new SalesCompany();
// Assign a specific computer builder to complete The computer This product
Computer computer = salesCompany.buildComputer(builder);
System.out.println(" Computers built : " + computer );
}
}
Now the code is quite perfect , That is, our buyers contact the computer sales center , Then the sales center calls the builder of the configuration that the user wants , What we created just now is a “ Low configuration computer builders ”, If we want to switch to a medium configuration computer , How do you do that ?
Now just add a medium configuration computer builder , Realization Builder The abstract class is OK
/**
* Low configuration computer
*/
public class MiddleConfigurationComputerBuilder extends ComputerBuilder {
private Computer computer;
public MiddleConfigurationComputerBuilder(){
computer = new Computer();
}
@Override
void buildCpu() {
computer.setCpu(" Intel core i7 processor ");
System.out.println("buildCpu: Intel core i7 processor ");
}
@Override
void buildGraphicsCard() {
computer.setGraphicsCard("16g Memory ");
System.out.println("buildGraphicsCard: 16g Memory ");
}
@Override
void buildDisplayScreen() {
computer.setDisplayScreen("2k 144hz Monitor ");
System.out.println("buildDisplayScreen: 2k 60hz Monitor ");
}
@Override
Computer getComputer() {
return computer;
}
}
Test it
public class Test {
public static void main(String[] args) {
MiddleConfigurationComputerBuilder builder = new MiddleConfigurationComputerBuilder();
// Create a computer sales center
SalesCompany salesCompany = new SalesCompany();
// Assign a specific computer builder to complete The computer This product
Computer computer = salesCompany.buildComputer(builder);
System.out.println(" Computers built : " + computer );
}
}
Running results
buildCpu: Intel core i7 processor
buildGraphicsCard: 16g Memory
buildDisplayScreen: 2k 60hz Monitor
Computers built : Computer{cpu=' Intel core i7 processor ', graphicsCard='16g Memory ', displayScreen='2k 144hz Monitor '}
In fact, here is an example of the builder pattern , Let's combine the concepts , Let's take a deeper look at the builder model
3、 ... and Builder pattern
( One ) Concept
Builder pattern : Separate the construction of a complex object from its representation , So that the same build process can create different representations
-
in other words , The product generation process Or say form , yes unchanged Of , And each part is optional , Namely its The internal appearance can change Of , This is also called the separation of change and invariance
-
In this case , Users just need to specify the type of build to get them , And the specific process and details don't need to be known
( Two ) Advantages and disadvantages
First , This mode has good encapsulation , Construction and presentation are separated , Each builder is independent of each other , It is good for decoupling and expansion , accord with “ Opening and closing principle ” At the same time, when the client calls , No need to know the product details
But it is also because of the constant part of the product generation process , It limits its use , At the same time, if something changes inside the product in the future , Then the builder has to modify it as well , Maintenance costs are not small
( 3、 ... and ) structure
According to the structure diagram above , Let's talk about the four roles ( except Client Beyond the caller )
- Product( Product role ): Complex objects made up of multiple components , The computer in the above example
- Builder( Abstract builder ): An interface that contains abstract methods for creating the various components of a product / abstract class , Generally, it also contains a method to return the result , As mentioned above ComputerBuilder class
- ConcreteBuilder( Specific builder ):Builder Implementation class of , As mentioned above Low configuration computer builders and Medium configuration computer builder
- Director( commander ): Call the component construction and assembly methods in the builder object , To create a complex object
- There is no specific product information in the commander
- It isolates the production process of customers and objects
( Four ) Applicable scenario
- The order affects the results of the same method , Like building a house , The foundation should be laid first , And then steel and cement
- The same object can assemble different parts or parts , At the same time, the results are different
- Product classes have complex internal structures , And these product objects have common features