我们有一个 Computer 类,属性如下,构造实例时分必须和可选。
public class Computer {
// 必须
private String cpu;
// 必须
private String ram;
// 可选
private int usbCount;
// 可选
private String keyboard;
// 可选
private String display;
}
不用 builder 设计模式,通常有两种传统的构造实例的方式:
第一种折叠构造函数模式(telescoping constructor pattern),即编写多个构造方法,每个构造方法中必须的属性必有,可选属性依次增加:
public class Computer {
...
public Computer(String cpu, String ram) {
this(cpu, ram, 0);
}
public Computer(String cpu, String ram, int usbCount) {
this(cpu, ram, usbCount, "罗技键盘");
}
public Computer(String cpu, String ram, int usbCount, String keyboard) {
this(cpu, ram, usbCount, keyboard, "三星显示器");
}
public Computer(String cpu, String ram, int usbCount, String keyboard, String display) {
this.cpu = cpu;
this.ram = ram;
this.usbCount = usbCount;
this.keyboard = keyboard;
this.display = display;
}
}
第二种 JavaBean 模式,就是一堆 getter&setter:
public class Computer {
...
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getRam() {
return ram;
}
public void setRam(String ram) {
this.ram = ram;
}
public int getUsbCount() {
return usbCount;
}
...
}
为了便于理解,先看简化版 builder 模式。还是要构建一个 Computer 实例,构造实例时属性分必须和可选。
public class Computer {
// 必须
private String cpu;
// 必须
private String ram;
// 可选
private int usbCount;
// 可选
private String keyboard;
// 可选
private String display;
private Computer(Builder builder){
this.cpu = builder.cpu;
this.ram = builder.ram;
this.usbCount = builder.usbCount;
this.keyboard = builder.keyboard;
this.display = builder.display;
}
public static class Builder{
// 必须
private String cpu;
// 必须
private String ram;
// 可选
private int usbCount;
// 可选
private String keyboard;
// 可选
private String display;
public Builder(String cup,String ram){
this.cpu=cup;
this.ram=ram;
}
public Builder setUsbCount(int usbCount) {
this.usbCount = usbCount;
return this;
}
public Builder setKeyboard(String keyboard) {
this.keyboard = keyboard;
return this;
}
public Builder setDisplay(String display) {
this.display = display;
return this;
}
public Computer build(){
return new Computer(this);
}
}
// 省略getter方法
}

上面简化版 builder 模式便于理解,经典的 builder 模式有 4 个角色。
Product 类: 最终要生成的对象,例如 computer 实例。
Builder 抽象类(或使用接口代替)。定义了构建 Product 的构建用抽象方法,其 Builder 实现类需要实现这些构建用方法。还会拥有一个用来返回最终产品的方法 Product getProduct()。
ConcreteBuilder: Builder 的实现类,实现 Builder 的抽象方法,编写此种 Builder 实现的方法。
Director: 决定如何使用 Builder 实现类提供的构建用方法。拥有一个负责组装的方法 void construct(Builder builder),在这个方法中通过组织并调用 builder 的方法,可以设置 builder。设置完成后,通过 builder 的构建方法 getProduct() 获得最终的产品。
public class Computer {
// 必须
private String cpu;
// 必须
private String ram;
// 可选
private int usbCount;
// 可选
private String keyboard;
// 可选
private String display;
public Computer(String cpu, String ram) {
this.cpu = cpu;
this.ram = ram;
}
public void setUsbCount(int usbCount) {
this.usbCount = usbCount;
}
public void setKeyboard(String keyboard) {
this.keyboard = keyboard;
}
public void setDisplay(String display) {
this.display = display;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", ram='" + ram + '\'' +
", usbCount=" + usbCount +
", keyboard='" + keyboard + '\'' +
", display='" + display + '\'' +
'}';
}
}
public abstract class ComputerBuilder {
public abstract void setUsbCount();
public abstract void setKeyboard();
public abstract void setDisplay();
public abstract Computer getComputer();
}
public class MacComputerBuilder extends ComputerBuilder {
private Computer computer;
public MacComputerBuilder(String cpu, String ram) {
computer = new Computer(cpu, ram);
}
@Override
public void setUsbCount() {
computer.setUsbCount(2);
}
@Override
public void setKeyboard() {
computer.setKeyboard("苹果键盘");
}
@Override
public void setDisplay() {
computer.setDisplay("苹果显示器");
}
@Override
public Computer getComputer() {
return computer;
}
}
public class LenovoComputerBuilder extends ComputerBuilder {
private Computer computer;
public LenovoComputerBuilder(String cpu, String ram) {
computer=new Computer(cpu,ram);
}
@Override
public void setUsbCount() {
computer.setUsbCount(4);
}
@Override
public void setKeyboard() {
computer.setKeyboard("联想键盘");
}
@Override
public void setDisplay() {
computer.setDisplay("联想显示器");
}
@Override
public Computer getComputer() {
return computer;
}
}
public class ComputerDirector {
public void makeComputer(ComputerBuilder builder){
builder.setUsbCount();
builder.setDisplay();
builder.setKeyboard();
}
}
public static void main(String[] args) {
// 1
ComputerDirector director=new ComputerDirector();
// 2
ComputerBuilder builder=new MacComputerBuilder("I5处理器","三星125");
// 3
director.makeComputer(builder);
// 4
Computer macComputer=builder.getComputer();
System.out.println("mac computer:"+macComputer.toString());
ComputerBuilder lenovoBuilder=new LenovoComputerBuilder("I7处理器","海力士222");
director.makeComputer(lenovoBuilder);
Computer lenovoComputer=lenovoBuilder.getComputer();
System.out.println("lenovo computer:"+lenovoComputer.toString());
}
输出:
mac computer:Computer{cpu='I5处理器', ram='三星125', usbCount=2, keyboard='苹果键盘', display='苹果显示器'}
lenovo computer:Computer{cpu='I7处理器', ram='海力士222', usbCount=4, keyboard='联想键盘', display='联想显示器'}