在软件开发中,如果一个对象的创建包含多个步骤,而且每个步骤又可以自由选择,那可以用建造者模式来创建该对象。像生活中各个电脑厂商生产电脑,要进行cpu、主板、内存、键盘等的组装,组装过程基本相同,只是各个步骤存在差异(a厂商使用intel的cpu,b厂商使用amd的cpu);还有在游戏中创建人物,选择姓名、性别、脸型、服装等。
定义
将一个复杂对象的构造与表示分离,意思是使用同样的构造过程可以创建不同的表示。
角色构成
产品角色:含有多个组成部件的对象,由具体建造者来创建各个零部件
抽象建造者角色:是一个包含创建产品各个零部件的抽象方法的接口,也会包括一个返回产品的方法
具体建造者角色:实现抽象建造者的接口,抽象方法被具体化
指挥者角色:包含一个产品组装过程的方法,方法内部会调用建造者的各个创建零部件的方法来完成组装
代码示例
/**
* 产品角色:电脑
*/
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();
}
/**
* 具体建造者:Mac电脑厂商
*/
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 static void makeComputer(ComputerBuilder builder){
builder.setUsbCount();
builder.setKeyboard();
builder.setDisplay();
}
}
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
ComputerBuilder builderA =
new MacComputerBuilder("i7", "海力士");
ComputerDirector.makeComputer(builderA);
Computer macComputer = builderA.getComputer();
ComputerBuilder builderB =
new LenovoComputerBuilder("i9", "三星");
ComputerDirector.makeComputer(builderB);
Computer LenovoComputer = builderB.getComputer();
System.out.println("苹果电脑:" + macComputer.toString());
System.out.println("联想电脑:" + LenovoComputer.toString());
}
}
运行结果:
优缺点
优点:
- 扩展性好,各个具体建造者相互独立,可以很容易地扩展具体建造者
- 客户端不用知道产品内部的组成细节,能很轻松地创建出复杂对象
缺点:
- 产品的组成部分是固定的,这限制了使用范围
- 如果产品的组成部分经常变动,则建造者、指挥者也要同步变动,后期维护成本较大
适用场景
- 多个零部件,可以装配到一个对象中,并且产生的结果又不相同
- 产品类非常复杂,或者产品类不同的调用顺序产生不同的结果
- 初始化一个对象特别复杂,参数多,而且很多参数都有默认值