一、简介
在软件开发过程中如果我们要创建一个复杂的对象,这个复杂对象由多个子部件按照一定步骤组成,对象的每个组成部分是不变的,但每一部分是可以灵活选择。
这时就可以使用建造者模式(构建模式),将对象的构造与它的表示相分离,使得相同的构建过程可以创建不同的表示(产品)。就比如:计算机都是由CPU、主板、内存、硬盘、显卡、显示器、键盘、鼠标等部件组装而成的,但对于不同种类的计算机,这些部件可能大不相同。
建造者模式和工厂模式的关注点不同:建造者模式注重目标对象由各部件的组装过程,而工厂方法模式更注重对象的创建过程,但两者可以结合使用。
建造者模式中主要有四类角色:
(1)产品角色(Product)
它是我们最终要创建的复杂对象,由具体建造者创建其各个组成部件
(2)抽象建造者(Builder)
它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 build()。
(3)具体建造者(ConcreteBuilder)
抽象建造者的实现类,完成复杂产品的各个部件的具体创建方法。
(4)指挥者(Director)
它调用建造者对象中的部件构造方法完成复杂对象的装配创建,在指挥者中不涉及具体产品的信息。
建造者模式的结构图如下:
二、使用场景
当我们想要创建的对象较复杂,由多个部件组成,对象的每个组成部分是不变的,但每一部分是可以灵活选择时,可以使用建造者模式。在StringBuilder中就用到了建造者模式,详情见扩展部分。
它的优点在于各个具体建造者相互独立,有利于系统的扩展。且客户端不必知道产品内部组成的细节,便于控制细节风险。
它的缺点在于产品的组成部分必须相同,这限制了其使用的范围。且如果产品的内部变化复杂,该模式会增加很多的建造者类。
三、举例
public class 建造者模式 {
public static void main(String[] args) {
Director dir=new Director(new ConcreteBuilder1());
Product pro=dir.construct();
pro.show();
}
}
//产品角色:包含多个组成部件的复杂对象
class Product{
private String partA;
private String partB;
private String partC;
public String getPartA() {
return partA;
}
public void setPartA(String partA) {
this.partA = partA;
}
public String getPartB() {
return partB;
}
public void setPartB(String partB) {
this.partB = partB;
}
public String getPartC() {
return partC;
}
public void setPartC(String partC) {
this.partC = partC;
}
public void show(){
System.out.println("对象内部组成部分分别为:"+partA+","+partB+","+partC);
}
}
//抽象建造者,包含创建产品各个子部件的抽象方法。
abstract class Builder{
//创建产品对象
protected Product pro=new Product();
public abstract Builder createPartA();
public abstract Builder createPartB();
public abstract Builder createPartC();
//返回产品对象
public Product build(){
return pro;
}
}
//具体建造者
class ConcreteBuilder1 extends Builder{
@Override
public Builder createPartA() {
pro.setPartA("建造partA(1)");
return this;
}
@Override
public Builder createPartB() {
pro.setPartB("建造partB(1)");
return this;
}
@Override
public Builder createPartC() {
pro.setPartC("建造partC(1)");
return this;
}
}
//指挥者:调用某个具体建造者中的方法完成复杂对象的创建
class Director{
private Builder builder;
public Director(Builder builder){
this.builder=builder;
}
public Product construct(){
builder.createPartA().createPartB().createPartC();
return builder.build();
}
}
四、扩展
(1) 建造者模式在应用过程中可以根据需要改变
如果创建的产品种类只有一种,只需要一个具体建造者,这时可以省略掉
抽象建造者,甚至可以省略指挥者角色。
(2)建造者模式在 StringBuilder 中的源码分析
StringBuilder 继承了一个 AbstractStringBuilder 类,AbstractStringBuilder 又实现了一个Appendable 接口。其中:
Appendable 接口定义了多个 append 方法(抽象方法),即 Appendable 为抽象建造者,定义了抽象方法
AbstractStringBuilder 实现了 Appendable 接口方法,这里的 AbstractStringBuilder 已经是具体建造者,只是不能实例化
StringBuilder 即充当了指挥者角色,同时也充当了具体的建造者,建造方法的实现是由 AbstractStringBuilder 完成,而 StringBuilder 继承了 AbstractStringBuilder,即使用的是继承复用,而不是聚合复用。
存储数据的底层字符数组char[] value,可以看成产品
五、参考
23种设计模式——创建型设计模式(5种)
java设计模式之构建模式
建造者模式以及在 StringBuilder 中的应用