生成器模式(Builder Pattern),也称建造者模式,属于构造型模式的一种。
定义
将一个复杂的对象的构建(builder)和它的表示(director)分离,使得同样的构建过程可以创建不同的表示。核心是给指导者一个生成器,但具体方式不指定。
类图及组成角色
四种角色(5种包括客户端):
产品(Product):具体生产器要构造的复杂对象,它的各个组成部分由ConcreteBuilder生成,生成过程由Director(指导类)控制。注意该类中只提供了get方法,这个看具体需求。
抽象生成器(Builder):声明了生成器应包含的创建产品各个组成部件的方法。注意,这些方法只是生成对象的各组成部分,各方法相互独立,方法间无时序关系,也不存在“总”的生成方法。另外,Builder应包含获取生成的产品的方法。
具体生产器(ConcreteProduct):实现Builder接口的类,具体生成器将实现Builder接口所定义的方法;每种不同的产品都有一个专属的ConcreteBuilder。
指导类(Director):用于控制产品的生成过程。Director的控制对象是Builder,即通过Director实现了对各类型产品的生成过程的重用。
客户端(Client):是生成器模式的使用者。对Client来说,生成的最终产品Product的类型是明确的,生成Product所使用的具体生成器ConcreteBuilder也是明确的。
优点
- 将复杂对象的构建和表示进行解耦,用户无需了解对象的具体组件,对象创建具有更大的灵活性。
- 可以更加精细有效地控制对象的构造过程。
- 满足开-闭原则:当增加新的具体生成器时,不必修改指挥者的代码。
应用
- 当系统创建结构复杂的对象时,对象的组成和装配方式须分离,构造方法中编写的对象无法分离。
- 构造过程必须允许被构造对象有不同表示时。
案例代码
//抽象类或接口
public abstract class Builder {
public abstract void buildPartA();
public abstract void buildPartB();
public abstract Product getBuildResult();
}
//指挥者类,用来指挥建造过程
public class Director {
public void construct(Builder builder) {
builder.buildPartA();
builder.buildPartB();
}
}
//具体建造者类
public class ConcreteBuilder1 extends Builder {
private Product product = new Product();
@Override
public void buildPartA() {
product.add("部件A");
}
@Override
public void buildPartB() {
product.add("部件B");
}
@Override
public Product getBuildResult() {
return product;
}
}
// 具体建造者类,建造的对象时Product,通过build使Product完善
public class ConcreteBuilder2 extends Builder {
private Product product = new Product();
@Override
public void buildPartA() {
product.add("部件X");
}
@Override
public void buildPartB() {
product.add("部件Y");
}
@Override
public Product getBuildResult() {
return product;
}
}
//产品类,由多个部件组成
public class Product {
List<String> parts = new ArrayList<String>();
// 添加产品部件
public void add(String part) {
parts.add(part);
}
// 列举所有的产品部件
public void show() {
System.out.println("---产品 创建---");
for (String part : parts) {
System.out.println(part);
}
}
}
//建造客户端
public class BuilderClient {
public static void main(String[] args) {
Director director = new Director();
Builder builder1 = new ConcreteBuilder1();
Builder builder2 = new ConcreteBuilder2();
director.construct(builder1);
Product product1 = builder1.getBuildResult();
product1.show();
director.construct(builder2);
Product product2 = builder2.getBuildResult();
product2.show();
}
}