建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。
背景
将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示
主要解决在软件系统中,有时候面临着”一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
实现
简化版
- 在Computer 中创建一个静态内部类 Builder,然后将Computer 中的参数都复制到Builder类中。
- 在Computer中创建一个private的构造函数,参数为Builder类型
- 在Builder中创建一个public的构造函数,参数为Computer中必填的那些参数,cpu 和ram。
- 在Builder中创建设置函数,对Computer中那些可选参数进行赋值,返回值为Builder类型的实例
- 在Builder中创建一个build()方法,在其中构建Computer的实例并返回
传统Builder 模式
如上图所示,builder模式有4个角色。
- Product: 最终要生成的对象,例如 Computer实例。
- Builder: 构建者的抽象基类(有时会使用接口代替)。其定义了构建Product的抽象步骤,其实体类需要实现这些步骤。其会包含一个用来返回最终产品的方法Product getProduct()。
- ConcreteBuilder: Builder的实现类。
Director: 决定如何构建最终产品的算法. 其会包含一个负责组装的方法void Construct(Builder builder), 在这个方法中通过调用builder的方法,就可以设置builder,等设置完成后,就可以通过builder的 getProduct() 方法获得最终的产品。
代码
简化版
public class Computer {
private final String cpu;//必须
private final String ram;//必须
private final int usbCount;//可选
private final String keyboard;//可选
private final 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方法
}
使用
Computer computer=new Computer.Builder("因特尔","三星")
.setDisplay("三星24寸")
.setKeyboard("罗技")
.setUsbCount(2)
.build();
传统Builder 模式
我们的目标Computer类:
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; } }
指导者类(Director)
public class ComputerDirector { public void makeComputer(ComputerBuilder builder){ builder.setUsbCount(); builder.setDisplay(); builder.setKeyboard(); } }
使用
首先生成一个director (1),然后生成一个目标builder (2),接着使用director组装builder (3),组装完毕后使用builder创建产品实例 (4)。public static void main(String[] args) { ComputerDirector director=new ComputerDirector();//1 ComputerBuilder builder=new MacComputerBuilder("I5处理器","三星125");//2 director.makeComputer(builder);//3 Computer macComputer=builder.getComputer();//4 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()); }