第十三章 建造者模式(Builder)
建造者模式的定义与特点
- 定义:将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建出不同的表示。
- 特点:建造者模式可以将一个产品的内部表象和生产过程相分离,从而可以通过一个建造过程而创建出不同内部表象的产品对象。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
如果使用建造者模式,那么用户就只需要指定建造的类型就可以得到他们,而具体的建造细节和过程就不需要知道了。
建造者(Builder)模式和工厂模式的关注点不同:建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程,但两者可以结合使用。
建造者模式的结构与实现
- 模式的结构
建造者(Builder)模式的主要角色如下。
- 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个子部件。
- 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
- 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
- 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
其结构如图所示:
- 模式的实现
Product:
public class Product {
public String partA;
public String partB;
public String partC;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
public void setPartC(String partC) {
this.partC = partC;
}
public void show() {
System.out.println("该产品由" + partA + "," + partB + "," + partC + "组成");
}
}
Builder:
public abstract class Builder {
public abstract void buildPartA();
public abstract void buildPartB();
public abstract void buildPartC();
public abstract Product getResult();
}
ConcreteBuilder1:
public class ConcreteBuilder1 extends Builder {
private Product product;
public ConcreteBuilder1() {
product = new Product();
}
public void buildPartA() {
product.setPartA("构建组件A");
}
public void buildPartB() {
product.setPartB("构建组件B");
}
public void buildPartC() {
product.setPartC("构建组件C");
}
public Product getResult() {
return product;
}
}
ConcreteBuilder2:
public class ConcreteBuilder2 extends Builder {
private Product product;
public ConcreteBuilder2() {
product = new Product();
}
public void buildPartA() {
product.setPartA("构建组件AA");
}
public void buildPartB() {
product.setPartB("构建组件BB");
}
public void buildPartC() {
product.setPartC("构建组件CC");
}
public Product getResult() {
return product;
}
}
Director:
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
/**
* 创建Product实例
*
* @return
*/
public Product construct() {
this.builder.buildPartA();
this.builder.buildPartB();
this.builder.buildPartC();
return this.builder.getResult();
}
}
测试类:
public class BuilderTest {
public static void main(String[] args) {
Builder builder1 = new ConcreteBuilder1();
Director director1 = new Director(builder1);
Product product1 = director1.construct();
product1.show();
Builder builder2 = new ConcreteBuilder2();
Director director2 = new Director(builder2);
Product product2 = director2.construct();
product2.show();
}
}
测试结果:
该产品由构建组件A,构建组件B,构建组件C组成
该产品由构建组件AA,构建组件BB,构建组件CC组成
Process finished with exit code 0
Builder是抽象类,定义了构建各个组件的方法,由子类去实现具体的构建方法。在Director类中调用具体实现类ConcreteBuilder的各个构建方法去组装Product的实例。
建造模式还有另一种写法,将Director省去,在客户端调用各个组件的构造方法,由用户去决定构建产品的各个组件的细节,也就是说将Director的权力移交给了调用方。
第二种方式的建造者类:
public abstract class Builder2 {
public abstract Builder2 buildPartA(String message);
public abstract Builder2 buildPartB(String message);
public abstract Builder2 buildPartC(String message);
public abstract Product build();
}
和第一种方式的区别就是各个方法的返回值类型为建造者,并且组件的细节是通过参数传进去的。
具体的建造者实现类:
public class ConcreteBuilder3 extends Builder2 {
private Product product;
public ConcreteBuilder3() {
product = new Product();
}
public Builder2 buildPartA(String message) {
product.setPartA(message);
return this;
}
public Builder2 buildPartB(String message) {
product.setPartB(message);
return this;
}
public Builder2 buildPartC(String message) {
product.setPartC(message);
return this;
}
public Product build() {
return product;
}
}
测试类:
ublic class Builder2Test {
public static void main(String[] args) {
Builder2 builder2 = new ConcreteBuilder3();
Product product = builder2.buildPartA("A组件").buildPartB("B组件").buildPartC("C组件").build();
product.show();
}
}
测试结果:
该产品由A组件,B组件,C组件组成
Process finished with exit code 0
这种方式使用更加灵活,可以根据用户需求自由定义更改内容。但是也违背了用户不需要知道构建细节的定义。
模式的应用场景
建造者(Builder)模式创建的是复杂对象,其产品的各个部分经常面临着剧烈的变化,但将它们组合在一起的算法却相对稳定,所以它通常在以下场合使用。
- 创建的对象较复杂,由多个部件构成,各部件面临着复杂的变化,但构件间的建造顺序是稳定的。
- 创建复杂对象的算法独立于该对象的组成部分以及它们的装配方式,即产品的构建过程和最终的表示是独立的。