1.概要介绍
1.1定义
建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
1.2适用环境
- 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
- 对象的创建过程独立于创建该对象的类。在建造者模式中引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类中。
- 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
1.3解决的问题
主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
2.模式结构
2.1UML图
2.2成员
- Builder:为创建一个Product对象的各个部件指定的抽象类或接口。
- ConcreteBuilder:具体的建造者,实现Builder接口,构造和装配各个部件。
- Product:具体的产品(被建造出来的产品)。
- Director:构建一个使用Builder接口的对象。
3.实例
假设我们现在饿了,去肯德基买吃的,因为是一个人嘛按照常理买套餐会划算一点,于是服务员为我们列出了很多种套餐的组合,有的套餐有中可、汉堡、薯条,有的套餐是鸡米花、鸡肉卷、果汁。我们就以生产该套餐为例,每一个套餐(产品)有三个单品(部件),部件是固定不变的,而产品的组合却多种多样,上代码:
代码示例:
Product类——产品类:
/**
* Created on 2020/3/15
* Package com.design_pattern.builder
*
* @author dsy
*/
public class Product {
//我们用一个集合来容纳产品的多个部件
List<String> parts = new ArrayList<>();
//添加产品部件的方法
public void add(String partName){
parts.add(partName);
}
@Override
public String toString() {
return "Product{" +
"parts=" + parts +
'}';
}
}
Builder 类——抽象建造者类:
/**
* Created on 2020/3/15
* Package com.design_pattern.builder
*
* @author dsy
*/
public abstract class Builder {//确定产品由三个部件partA、partB、partC组成,并声明一个得到产品建造后结果的方法getResult
public abstract void BuildPartA();
public abstract void BuildPartB();
public abstract void BuildPartC();
public abstract Product getResult();
}
ConcreteBuilder1 类——具体建造者类1:
/**
* Created on 2020/3/15
* Package com.design_pattern.builder
*
* @author dsy
*/
public class ConcreteBuilder1 extends Builder { //具体建造者类
private Product product = new Product(); //实例化一个产品
@Override
public void BuildPartA() { //为产品添加各个部件
product.add("可乐");
}
@Override
public void BuildPartB() {
product.add("薯条");
}
@Override
public void BuildPartC() {
product.add("汉堡");
}
@Override
public Product getResult() { //返回产品
return product;
}
}
ConcreteBuilder2 类——具体建造者类2:
public class ConcreteBuilder2 extends Builder {
private Product product = new Product();
@Override
public void BuildPartA() {
product.add("可乐");
}
@Override
public void BuildPartB() {
product.add("汉堡");
}
@Override
public void BuildPartC() {
product.add("鸡米花");
}
@Override
public Product getResult() {
return product;
}
}
Construct类——指挥者类:
/**
* Created on 2020/3/15
* Package com.design_pattern.builder
*
* @author dsy
*/
public class Director {
public void Construct(Builder builder){ //用来指挥建造过程(通常有顺序之分)
builder.BuildPartA();
builder.BuildPartB();
builder.BuildPartC();
}
}
测试类:
/**
* Created on 2020/3/15
* Package com.design_pattern.builder
*
* @author dsy
*/
public class Test {
public static void main(String[] args) {
Director director = new Director(); //指挥者
Builder builder1 = new ConcreteBuilder1(); //具体建造者1
director.Construct(builder1); //指挥者指挥具体建造者1来创建产品
Product product = builder1.getResult(); //由建造者1生产出来的产品
System.out.println(product);
Builder builder2 = new ConcreteBuilder2(); //具体建造者2
director.Construct(builder2);//指挥者指挥具体建造者2来创建产品
Product product2 = builder2.getResult();//由建造者2生产出来的产品
System.out.println(product2);
}
}
打印输出:
Product{parts=[可乐, 薯条, 汉堡]}
Product{parts=[可乐, 汉堡, 鸡米花]}
4.优缺点分析
优点:
- 在建造者模式中, 建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就好了。
- 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象 。
- 可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
缺点:
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。