最近在公司阅读代码时发现有些实体类具有很多的属性。于是就想到了用建造者模式进行优化一下。
跟工厂模式和抽象工厂模式一样,建造者模式也属于创建型设计模式。该设计模式主要用于解决在工厂模式和抽象工厂模式中由于对象具有众多属性所带来的问题。这些问题主要三个方面:
- 在客户端程序与工厂类传递参数的参数的过程中很容易出错,因为大部分情况下,参数类型相同,而且对于客户端程序来说这是比较难以维护。
- 一些变量可能是可选的,但在工厂模式中,所有的变量必须要被强制传输,其中可选参数被赋值为
NULL
。 - 如果对象不那么的轻量,而且创建时又相对复杂,这种复杂性也将是工厂模式混乱的一部分。
对于大量的属性问题,我们看上去可以通过提供一个带有必须参数的构造函数以及getter
/setter
方法来解决,但是这又带来了对象状态的不一致性,除非所有的属性都被明确设置。
建造者模式则通过渐进式创建对象并最终返回该对象的方式巧妙的解决了上述问题。
我们来看一下建造者模式的实现。
- 首先你得创建一个静态内部类
Builder
,并把所有外部类的参数复制到该类中。建议在命名该内部类时,尽量在外部类后面加上Builder
字样,例如,外部类名为Computer
,该内部类名字为ComputerBuilder
。 - 该内部建造者类要具有一个
public
类型的构造函数,该构造函数以必需的属性值为参数。 - 建造者类具有赋值可选参数的方法,并且方法的返回值时该类本身。
- 最后,建造者类须提供一个类似于
build()
的方法,返回一个外部类实例。因此外部类需要一个以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);
}
}
}
注意此时Computer
类只有getter
方法,而且没有公有的构造函数,那么获取Computer
实例对象的方法就只能通过ComputerBuilder
类实现了。
建造者模式的使用也非常简单。
Computer comp = new Computer.ComputerBuilder(
"500 GB", "2 GB").setBluetoothEnabled(true)
.setGraphicsCardEnabled(true).build();
在JDK
中例如StringBuilder
、StringBuffer,Grpc中的Response、Request
也都使用了该设计模式。