设计模式从入门到放弃(二)构建者模式
构建者模式 Builder
构建者模式要求将构建的过程和表示过程进行分离。将复杂的构建过程分成若干的步骤一步一步进行构建,使得每个部分更加灵活。客户端不需要知道构建的细节,构建步骤相互独立,利于扩展。
构建者模式核心角色
- Product(产品角色): 一个具体的产品对象。
- Builder(抽象建造者): 创建一个 Product 对象的各个部件指定的 接口或者抽象类。
- ConcreteBuilder(具体建造者): 实现接口,构建和装配各个部件。
- Director(指挥者): 构建一个使用 Builder 接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。
UML 示意图
代码实现
// 具体的构建出来产品对象 充当产品角色(Product)
@Data
public class Product {
private String step1;
private String step2;
private String step3;
}
// 抽象Builder 类 抽象 构建的步骤 充当 抽象建造者(Builder)
public abstract class AbstractBuilder {
protected Product product = new Product();
public abstract void step1();
public abstract void step2();
public abstract void step3();
public Product getResult(){
return this.product;
}
}
// 具体的构建过程的实现 充当 ConcreteBuilder(具体建造者)
public class BuilderImpl1 extends AbstractBuilder {
@Override
public void step1() {
System.out.println("Impl1 step1");
product.setStep1("Impl1 step1");
}
@Override
public void step2() {
System.out.println("Impl1 step2");
product.setStep2("Impl1 step2");
}
@Override
public void step3() {
System.out.println("Impl1 step3");
product.setStep3("Impl1 step3");
}
}
// 构建的指挥者 定义构建的细节过程得到最终对象 它主要是用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程
public class BuildDirector {
private AbstractBuilder builder;
public BuildDirector(AbstractBuilder builder) {
this.builder = builder;
}
public Product getResult() {
builder.step1();
builder.step2();
builder.step3();
return builder.getResult();
}
}
// 具体使用
public class BuilderDemoTest {
public static void main(String[] args) {
// 先创建具体的构建者实现
BuilderImpl1 builderImpl1 = new BuilderImpl1();
// 组合指挥者和构建者具体实现 得到最终产品
BuildDirector buildDirector = new BuildDirector(builderImpl1);
System.out.println(buildDirector.getResult());
}
}
JDK源码分析
StringBuilder使用了到了非标准的构建者模式
StringBuilder 继承> AbstractStringBuilder 实现> Appendable接口
Appendable接口中定义了三个append方法 对应构建者角色的抽象构建者角色 只是不能实例化
Appendable append(CharSequence csq) throws IOException;
其AbstractStringBuilder 实现了Appendable接口的 append方法 类似 具体实现的构建者角色
public AbstractStringBuilder append(String str) {
if (str == null) {
return appendNull();
}
int len = str.length();
ensureCapacityInternal(count + len);
putStringAt(count, str);
count += len;
return this;
}
StringBuilder 充当的指挥者 调用父类的append方法 返回一个具体的Stringbuilder产品对象
@Override
@HotSpotIntrinsicCandidate
public StringBuilder append(String str) {
super.append(str);
return this;
}
使用细节
- 屏蔽产品内部组成细节,使得产品本身和组成的过程解耦,使用相同的构建过程可以生成不同的产品
- 具体实现抽象构建者的对象相互独立,扩展性强,客户端只需要传入不同的构建者实现就可以得到不同的产品对象
- 可以精细化控制构建的过程,把复杂个构建过程分解到不同的方法中
- 使用构建者模式需要产品拥有比较多的相似点,如果产品差异过大就不适合使用构建者模式