模式动机
在现实生活中存在一些复杂的产品,如汽车,它有方向盘、轮胎、发动机灯组件构造而成,但是用户无需知道各个组件的生产过程与具体的构造过程,只需要最后得到一个汽车即可。
在软件设计中,也有一些复杂的对象,它拥有一系列成员属性。复杂对象相当于一辆汽车,对象的属性则相当于汽车的部件,建造产品的过程相当于组合部件的过程。由于这个过程过于复杂,因此这些部件的组合过程往往被外部化到一个称为建造者的对象中,建造者将建造完毕的复杂对象返回给客户端。用户无需关心该对象所包含的属性以及他们的组装方式,这就是建造者模式的模式动机。
模式定义
将一个复杂对象的表示与构造分离,使得同样的构造过程可以创建不同的表示。建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。
模式结构
建造者模式包含以下角色:
- Builder:抽象建造者
- ConcreteBuilder:具体建造者
- Director:指挥者
- Product:产品角色
上图中,+号代表是public类型,-号代表是private类型。
时序图
用户通过异步消息create,激活ConcreteBuilder类。之后用户向Director发送同步消息,要求创建Builder类,然后再用户再向Director发送同步消息constuct(),Builder类开始依次执行buildPartA、buildPartB、buildPartC、getResult的同步消息,最终返回Product类。
代码实现
//产品类
public class Product {
private String buildA;
private String buildB;
private String buildC;
private String buildD;
public String getBuildA() {
return buildA;
}
public void setBuildA(String buildA) {
this.buildA = buildA;
}
public String getBuildB() {
return buildB;
}
public void setBuildB(String buildB) {
this.buildB = buildB;
}
public String getBuildC() {
return buildC;
}
public void setBuildC(String buildC) {
this.buildC = buildC;
}
public String getBuildD() {
return buildD;
}
public void setBuildD(String buildD) {
this.buildD = buildD;
}
}
//抽象建造类
abstract class Builder {
abstract void bulidA();
abstract void bulidB();
abstract void bulidC();
abstract void bulidD();
abstract Product getProduct();
}
//具体建造类
public class ConcreteBuilder extends Builder{
private Product product;
@Override
void bulidA() {
product.setBuildA("汽车底盘");
}
@Override
void bulidB() {
product.setBuildB("汽车发动机");
}
@Override
void bulidC() {
product.setBuildC("汽车座椅");
}
@Override
void bulidD() {
product.setBuildD("汽车外壳");
}
@Override
Product getProduct() {
return product;
}
}
//指挥类
public class Director {
public Product create(Builder builder) {
builder.bulidA();
builder.bulidB();
builder.bulidC();
builder.bulidD();
return builder.getProduct();
}
}
模式分析
- 抽象建造者类中定义了产品的创建方法和返回方法
- 建造者模式中新增了一个指挥类Director类,该类的作用有两个:1、隔离用户与生成过程;2、控制产品的生成过程。指挥类的存在,使得用户只需要知道建造者的类型,即可通过指挥类调用建造者的相关方法,返回一个完整的产品对象。
建造者模式将复杂度对象的构建与表示分离开,这使得同样的构建过程可以创建出不同的表现。
模式的优缺点
优点
- 客户端不必知道产品内部组成的细节,
将产品本身与产品的创建过程解耦
,使得相同的创建过程可以创建不同的产品对象
。 - 建造者相互独立,用户可以通过使用不同的建造者得到不同的产品,也可以通过定义新的建造者得到新的产品。
可以更加精细地控制产品的创建过程
。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。符合开闭原则
。用户增加新的建造者无需修改现用代码,指挥类是针对抽象建造者编程
,系统可扩展性强。
缺点
- 建造的产品具有较多相似的地方,如果产品间差异较大则无法使用建造者模式。
- 如果产品内部过于复杂,相应的的系统也会变得庞大。
适用环境
- 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
- 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
对象的创建过程独立于创建该对象的类。
在建造者模式中引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类中。
模式扩展
建造者模式与抽象工厂模式的比较:
建造者模式返回一个组装好的完整产品
,而抽象工厂模式返回
一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族
。- 建造者模式可以不调用具体的建造类,通过调用指挥类,一步步构建一个复杂对象最终获得一个完整的产品。
如果将抽象工厂模式看成 汽车配件生产工厂 ,生产一个产品族的产品,那么建造者模式就是一个 汽车组装工厂 ,通过对部件的组装可以返回一辆完整的汽车。
参考
https://www.jianshu.com/p/47329a94f5dc
https://design-patterns.readthedocs.io/zh_CN/latest/creational_patterns/builder.html#