当一个类构造器需要传入很多参数时,如果创建这个类的实例,代码可读性就会非常差,而且还很容易引入错误,那么此时就可以利用建造者模式进行重构。
这里我们拿电脑实例类进行举例:
第一步:
由于我们现在是使用建造者模式来进行重构,所以就不能让外界直接调用Computer类的构造方法,对Computer类的构造方法私有化,然后在Computer类中定义一个静态的内部类Builder,并且在构造方法里传递一个构建器:
package pattern.builder.demo2;
/**
* @author ***
* @create 2022-05-19 12:45
*/
public class Computer{
/**
* cpu
*/
private String cpu;
/**
* 显示器
*/
private String screen;
/**
* 显卡
*/
private String gpu;
/**
* 主板
*/
private String mainboard;
private Computer(Builder builder) {
}
public static final class Builder{
}
}
第二步:
在它里面提供四个成员变量,分别对应外部类属性,并且还要提供对应的方法进行这些属性(部件)的构建:
package pattern.builder.demo2;
/**
* @author ***
* @create 2022-05-19 12:45
*/
public class Computer{
/**
* cpu
*/
private String cpu;
/**
* 显示器
*/
private String screen;
/**
* 显卡
*/
private String gpu;
/**
* 主板
*/
private String mainboard;
private Computer(Builder builder) {
}
public static final class Builder{
private String cpu; //cpu
private String screen; //显示器
private String gpu; //显卡
private String mainboard; //主板
public Builder cpu(String cpu){
this.cpu = cpu;
return this;
}
public Builder screen(String screen){
this.screen = screen;
return this;
}
public Builder gpu(String gpu){
this.gpu = gpu;
return this;
}
public Builder mainboard(String mainboard){
this.mainboard = mainboard;
return this;
}
}
}
第三步:
完善Computer类中的构造方法,即把构建者对象中的成员变量直接赋给Computer类中的成员变量,并在Builder内部类里面定义一个创建Phone对象的方法(因为Computer类中的构造方法私有了,所以外界是不能直接调用Computer类的构造方法去创建Computer对象的。既然这样,那么我们只能使用Builder内部类去构建Computer对象)
package pattern.builder.demo2;
/**
* @author ***
* @create 2022-05-19 12:45
*/
public class Computer{
/**
* cpu
*/
private String cpu;
/**
* 显示器
*/
private String screen;
/**
* 显卡
*/
private String gpu;
/**
* 主板
*/
private String mainboard;
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.screen = builder.screen;
this.gpu = builder.gpu;
this.mainboard = builder.mainboard;
}
public static final class Builder{
private String cpu; //cpu
private String screen; //显示器
private String gpu; //显卡
private String mainboard; //主板
public Builder cpu(String cpu){
this.cpu = cpu;
return this;
}
public Builder screen(String screen){
this.screen = screen;
return this;
}
public Builder gpu(String gpu){
this.gpu = gpu;
return this;
}
public Builder mainboard(String mainboard){
this.mainboard = mainboard;
return this;
}
//使用构建者创建Computer对象
public Computer builder(){
return new Computer(this);
}
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", screen='" + screen + '\'' +
", gpu='" + gpu + '\'' +
", mainboard='" + mainboard + '\'' +
'}';
}
}
最后,不要忘了在Computer类中重写toString方法,以方便我们测试。
测试类:
package pattern.builder.demo2;
/**
* @author ***
* @create 2022-05-18 20:56
*/
public class Client {
public static void main(String[] args) {
//创建电脑对象,通过构建者对象获取手机对象
Computer computer = new Computer.Builder()
.cpu("intel")
.screen("三星屏幕")
.gpu("GTX3080")
.mainboard("华硕主板")
.builder();
// 由于cpu、screen等这些方法返回的都是当前对象,所以我们可以使用链式编程
System.out.println(computer);
}
}
运行结果:
使用这种方式构建哪个属性(组件),我们是一目了然的。例如调用cpu方法,我们就知道要进行组装的就是cpu,并且现在是把属性(组件)的构建顺序交给了客户,客户想怎么去构建,就按照他的顺序去构建
重构后的代码使用起来更方便,某种程度上也可以提高开发效率,可以链式编程,而且代码的可读性比之前更高了。