建造者模式
Builder Pattern
简介
定义:将一个复杂对象的构建与表示分离
作用:在用户不知道 对象的建造过程和细节的情况下可以直接创建复杂对象
角色
-
Builder 抽象的,由ConcreteBuilder来实现
- 抽象建造者: 为创建一个产品指定构造部件的方法,由具体建造者去实现
- 具体实现来依赖Builder接口 面向接口编程
- 例子:建房子的图纸,这张图纸有建房子的步骤(打地基,打钢筋,装修),无论是建高楼还是别墅你都要来实现这个Builder
-
ConcreteBuilder 具体构建者去实现Builder
- 具体建造者: 实现抽象建造者的方法,构造或装配对象
- Builder的实现类,创建复杂对象的细节在实现方法中
- 例子:建高楼(具体建造者)根据图纸(抽象建造者)给出的步骤去实现详细过程
-
Product 产品类(我们想要的最终结果)
- 产品: 表示被建造的复杂对象,内部由ConcreteBuild去实现,最终由Director生产出来
- 最终被创建出来的产品
- 例子:房子被创建出来了
-
Director Builder 的创建者
- 指挥者: 调用ConcreteBuilder实现的建造方法,生产出Product产品
- 接收Builder的实现类ConcreteBuilder,调用创建对象详细方法,返回产品
- 例子: 指挥创建房子
例子
如果要造一个房子,这个房子是高楼,那么根据建造者模式的角色分类:
Builder:建房子的图纸 (建房子步骤:打地基,打钢筋,装修…)
ConcreteBuilder: 高楼 (实现图纸上步骤的详细方案)
Director: 指挥工人创建房子(高楼)
Product: 房子
如果还想造其他房子比如别墅,只需要创建别墅的ConcreteBuilder去实现Builder即可 (实现别墅打地基,打钢筋,装修的详细方案)
不同的ConcreteBuilder 根据自身情况去实现 Builder定义的方法,ConcreteBuilder聚合Product,在实现Builder定义的方法时就是对Product进行"设置",最后ConcreteBuilder交给Director指挥具体构建步骤
代码
Builder可以使用接口或抽象类 我这里使用抽象类
//产品: 房子 由具体建造者来创建产品的内部
public class Product {
private String buildA;
private String buildB;
private String buildC;
@Override
public String toString() {
return "Product{" +
"buildA='" + buildA + '\'' +
", buildB='" + buildB + '\'' +
", buildC='" + buildC + '\'' +
'}';
}
// 字段的get/set方法...
}
//抽象建造者:像图纸一样 规定好造房子步骤,让具体建造者去依赖 (面向接口编程)
public abstract class Builder {
abstract void buildA();//打地基
abstract void buildB();//打钢筋
abstract void buildC();//装修
abstract Product getProduct();
}
//具体建造者 : 工人 按照图纸(建造者)要求 打造 产品(房子)
public class ConcreteBuilder extends Builder {
private Product product;
public ConcreteBuilder() {
this.product = new Product();
}
@Override
void buildA() {
product.setBuildA("打地基");
System.out.println("打地基");
}
@Override
void buildB() {
product.setBuildB("打钢筋");
System.out.println("打钢筋");
}
@Override
void buildC() {
product.setBuildC("装修");
System.out.println("装修");
}
@Override
Product getProduct() {
return product;
}
}
//指挥并构造一个使用Builder的对象 核心 负责指挥一个房子如何去建造
public class Director {
//指挥建造房子
public Product build(Builder builder){
builder.buildA();
builder.buildB();
builder.buildC();
return builder.getProduct();
}
}
//客户端
public class Client {
public static void main(String[] args) {
//指挥 建造房子 最终得到这个房子
//表示层
Director director = new Director();
Product product = director.build(new ConcreteBuilder());
/*
曾经创建层表示层未分离:
Product p = new Product();
p.setBuildA();
p.setBuildB();
p.setBuildC();
*/
System.out.println(product.toString());
}
}
将复杂对象的创建层与表示层分离
创建层: Director,ConcreteBuilder
表示层: Client
如果需要构造其他房子:高楼,小别墅(这些是ConcreteBuilder具体构建者)等
- 需要继承Builder(抽象构建者),实现具体构建者的创建细节 工人根据图纸创建房子
- 然后把某个具体构建者ConcreteBuilder传给Director 指挥工人去创建房子
- Director来指挥Builder 指挥创建房子
总结
- 优点
- 产品的创建和表示分离,客户端不必知道产品内部组成细节(房子内部组成细节是工人去做的,我不用知道)如果想要改变产品内部,只需要定义一个新的具体建造者
- 缺点
- 建造者模式建造的产品一般具有较多相同点,如果差异大,不适合使用建造者模式
- 应用场景
- 产品对象内部很复杂,产品对象有很多共同点