简介
建造者模式又称为builder模式,一般用来构建复杂对象,将复杂对象的创建与表示分离,用户不需要了解建造的过程和细节。完整的建造者模式的结构模型如下:
完整的建造者模式包含四个角色:
builder:指定创建对象的各个部件的接口;
ConcreteBuilder:具体建造者,实现builder的接口;
product:最终构建成的具体产品;
director:指挥者直接和客户进行需求沟通,并将客户创建产品的请求划分为对各个零件的创建请求,再将这些请求委托给具体建造者建造;
模式实现
以网上订购电脑举例,产品为电脑(部件包括主机、显示器、电源线三部分),指挥者相当于电商平台,而建造者为电脑厂家。用户和平台沟通,平台委托厂家创建电脑并转交给用户。
产品,即电脑类:
@Data
public class Computer implements Serializable {
...
}
建造者接口:
public interface ComputerBuilder {
void buildMainEngine(); // 建造主机
void buildMonitor(); // 建造显示器
void buildPowerCord(); // 建造电源线
Computer returnComputer(); // 返还电脑产品
}
具体建造者:
public class ComputerConcreteBuilder implements ComputerBuilder {
private Computer computer = new Computer();
@Override
public void buildMainEngine() {
System.out.println("创建主机。。");
}
@Override
public void buildMonitor() {
System.out.println("创建显示器。。");
}
@Override
public void buildPowerCord() {
System.out.println("创建电源线。。");
}
@Override
public Computer returnComputer() {
return computer;
}
}
指挥者:
@NoArgsConstructor
public class ComputerDirector {
private ComputerBuilder computerBuilder;
public ComputerDirector(ComputerBuilder computerBuilder) {
this.computerBuilder = computerBuilder;
}
public Computer buildComputer() {
computerBuilder.buildMainEngine();
computerBuilder.buildMonitor();
computerBuilder.buildPowerCord();
return computerBuilder.returnComputer();
}
}
实际使用:
public static void main(String[] args) {
Computer computer = new ComputerDirector().buildComputer();
}
这样,一个完整的建造者模式流程就完成了。
建造者模式一般一个具体建造者只对应一个产品,如果有多个产品,则添加多个具体建造者。
模式退化
省略抽象建造者角色
如果确定只需要一个具体建造者的话,那么抽象建造者是可以省略的,抽象建造者角色的存在是为了规范具体建造者的行为,如果系统只有一个具体建造者,那么这个规范者角色就不需要了。
省略指挥者角色
如果抽象建造者角色被省略了,那么指挥者角色也可以被省略,这时候具体建造者同时扮演指挥者和建造者两个角色。
省略单独的产品角色
这种情况适用于建造者构造的对象就是建造者自身,建造者同时扮演指挥者、建造者、产品三个角色。
jdk中的建造者模式
jdk中的建造者模式常见的就是SringBuffer和StringBuilder了,其中非线程安全的StringBuilder最为常用。AbstractStringBuilder作为抽象建造者,StringBuidler作为具体建造者,建造的对象是String,通过toString方法返回。
此外,常用的链式调用也可以视为建造者模式,例如:
@Data
@Accessors(chain = true)
public class Computer implements Serializable {
private static final long serialVersionUID = 3991323827696929155L;
private String mainEngine;
private String monitor;
private String powerCord;
public static void main(String[] args) {
Computer computer = new Computer().setMainEngine("主机").setMonitor("显示器").setPowerCord("电源线");
}
}
其中Computer为产品,setMainEngine()
、setMonitor()
、setPowerCord()
是构建产品的部件方法,这种就是极简类型的建造者模式。
与其他模式对比
与抽象工厂模式
在抽象工厂模式中,每一次工厂对象被调用时都会返回一个产品对象,这个产品位于不同的产品等级结构中的一环,可能是一个最终的产品的一部分,而客户端后续把产品组装到成一个更大更复杂的产品;建造者模式则返回一个完整的、最终的产品。
抽象工厂模式中,客户端直接调用工厂方法获取所需产品对象,而建造者模式中,客户端可以通过指挥者间接获取对象,且建造者类侧重于一步步构造一个复杂对象,返回一个完整的对象。
还使用上面例子,抽象工厂模式返回产品族中的一个产品,例如只返回电脑主机;而建造者模式直接返回整个电脑。
与模板模式
当建造者模式退化到没有指挥者,且抽象建造者使用抽象类,这样完全可能变为模板模式,只要将具体构建产品部件方法的顺序固定到返还产品方法中,并将返还产品不可重写,就是一个合格的模板模式。
实质上,兵无常势,水无常形,实际代码中严格按照设计模式定义的实现并不多,大多是退化之后的模式,而很多模式退化之后都非常相似,甚至可以互相转化。