本文翻译自:https://www.journaldev.com/1425/builder-design-pattern-in-java
Builder Design Pattern
-
建造者模式用于解决工厂模式和抽象工厂模式的一些诟病,即当对象中包含较多属性时该如何优雅的创建对象;
-
工厂模式和抽象工厂模式存在三个问题;
- 当创建对象时,许多参数的类型是一样的且难以维护传参的顺序;
- 有些参数可能是可选的,但是在工厂模式中,我们会被迫传入null值;
- 如果对象很“笨重”且其创建过程很复杂,那就要对Factory 类的代码做侵入,这样将使代码的可读性降低;
-
我可以通过提供一个构造器解决这个问题,并且添加不同的set方法控制可选参数的传入;
Builder Design Pattern in Java
- 首先需要在被建造者内部创建一个静态内部类——Builder class(建造者),然后将所有外部类的属性拷贝到静态内部类中,其次我们需要遵循一些命名规则,如果被创建的类的名字是Computer,那么建造类的名字应该是ComputerBuilder;
- 建造类应该有一个公有的构造方法,这个构造方法可以将所有需要的属性和参数传入;
- 建造类应该有可选参数的set方法,并且在设置可选属性后返回同一个建造对象;
- 最后一步是在建造类内部提供一个可以返回被创建对象的build()方法,因此我们需要一个私有的方法,其参数为创建类;
- 这里有一个关于建造者模式的小case:
package com.journaldev.design.builder;
public class Computer {
//required parameters
private String HDD;
private String RAM;
//optional parameters
private boolean isGraphicsCardEnabled;
private boolean isBluetoothEnabled;
public String getHDD() {
return HDD;
}
public String getRAM() {
return RAM;
}
public boolean isGraphicsCardEnabled() {
return isGraphicsCardEnabled;
}
public boolean isBluetoothEnabled() {
return isBluetoothEnabled;
}
private Computer(ComputerBuilder builder) {
this.HDD=builder.HDD;
this.RAM=builder.RAM;
this.isGraphicsCardEnabled=builder.isGraphicsCardEnabled;
this.isBluetoothEnabled=builder.isBluetoothEnabled;
}
//Builder Class
public static class ComputerBuilder{
// required parameters
private String HDD;
private String RAM;
// optional parameters
private boolean isGraphicsCardEnabled;
private boolean isBluetoothEnabled;
public ComputerBuilder(String hdd, String ram){
this.HDD=hdd;
this.RAM=ram;
}
public ComputerBuilder setGraphicsCardEnabled(boolean isGraphicsCardEnabled) {
this.isGraphicsCardEnabled = isGraphicsCardEnabled;
return this;
}
public ComputerBuilder setBluetoothEnabled(boolean isBluetoothEnabled) {
this.isBluetoothEnabled = isBluetoothEnabled;
return this;
}
public Computer build(){
return new Computer(this);
}
}
}
-
注意看,Compute仅仅只有get方法并且没有公开的构造方法,因此创造Computer只有通过ComputerBuilder 类;
-
接下来有一个测试例子,展示了如何通过ComputerBuilder创建一个Computer 对象;
package com.journaldev.design.test;
import com.journaldev.design.builder.Computer;
public class TestBuilderPattern {
public static void main(String[] args) {
//Using builder to get the object in a single line of code and
//without any inconsistent state or arguments management issues
Computer comp = new Computer.ComputerBuilder(
"500 GB", "2 GB").setBluetoothEnabled(true)
.setGraphicsCardEnabled(true).build();
}
}
Builder Design Pattern Example in JDK
- jdk源码中使用了建造者模式的例子:
- java.lang.StringBuilder#append() (unsynchronized)
- java.lang.StringBuffer#append() (synchronized)
网友评论