考虑使用Builder模式
日常开发中,大部分都基于构造方法或普通的javabean set方式来创建填充对象。
当参数众多类型相同,同时包含一些必填与非必填参数等情况时,Builder模式是一个很好的实践方式。
案例:
设计创建配备一台PC电脑,其中显示屏/主机/鼠标/键盘作为必填的属性; 而音箱/摄像头等作为非必填属性。 我们分别通过构造方法,javabean set,以及Builder三种模式来创建进行对比。
public class TestPcComputer {
private String dispaly;
private String host;
private String keyboard;
private String mouse;
// 非必填
private String speaker;
private String camera;
}
1. 通过构造方法
public TestPcComputer(String dispaly, String host, String keyboard, String mouse) {
this.dispaly = dispaly;
this.host = host;
this.keyboard = keyboard;
this.mouse = mouse;
}
public TestPcComputer(String dispaly, String host, String keyboard, String mouse, String speaker) {
this.dispaly = dispaly;
this.host = host;
this.keyboard = keyboard;
this.mouse = mouse;
this.speaker = speaker;
}
public TestPcComputer(String dispaly, String host, String keyboard, String mouse, String speaker, String camera) {
this.dispaly = dispaly;
this.host = host;
this.keyboard = keyboard;
this.mouse = mouse;
this.speaker = speaker;
this.camera = camera;
}
为了支持必填与非必填属性,对构造方法进行重载。比如我们创建一个包含camera的电脑:
TestPcComputer pc = new TestPcComputer("显示器", "主机", "键盘", "鼠标", null, "摄像头")
可以看到当我们只包含其中一些非必填字段时,需要根据构造方法的签名,将不包含的非必填字段也进行传值。
另外,如果客户端调用创建对象没有文档或源码, 只是看到构造方法分别有不同数量的string类型简直就是。。。
2. 通过JavaBean set方式
针对上面的属性分别生成get()&set()方法(此处省略代码部分)。
同样我们创建一个包含camera的电脑:
TestPcComputer pc = new TestPcComputer();
pc.setDispaly("显示器");
pc.setHost("主机");
pc.setKeyboard("键盘");
pc.setMouse("鼠标");
pc.setCamera("摄像头");
可以看到比构造方法可读性要好,但是分不清哪些是必填的哪些是可选的。 另外在pc对象完成构造之后还是可变的。
3. 通过Builder方式
创建Builder内部构造类:
public class TestPcComputer {
... //省略属性
public static class Builder {
private String dispaly;
private String host;
private String keyboard;
private String mouse;
private String speaker;
private String camera;
public Builder(String dispaly, String host, String keyboard, String mouse) {
this.dispaly = dispaly;
this.host = host;
this.keyboard = keyboard;
this.mouse = mouse;
}
public Builder speaker(String speaker) {
this.speaker = speaker;
return this;
}
public Builder camera(String camera) {
this.camera = camera;
return this;
}
public TestPcComputer build() {
TestPcComputer pc = new TestPcComputer();
pc.setDispaly(this.dispaly);
pc.setHost(this.host);
pc.setKeyboard(this.keyboard);
pc.setMouse(this.mouse);
pc.setCamera(this.camera);
return pc;
}
}
}
同样我们创建一个包含camera的电脑:
TestPcComputer pc = new TestPcComputer.Builder("显示器", "主机", "键盘", "鼠标")
.camera("摄像头").build();
可以看到使用Builder模式后,客户端创建对象时代码更容易编写及可读。 当增加更多的可选属性时也更容易扩展。
总结
- 对于一些简单的对象创建使用构造方法或set方式更好。
- 对于一些对象需要定制化参数,可以借助Builder模式更好的描述创建的过程。
- 使用Builder也需要付出一些代价,如:每次会多创建一个Builder对象。