Java 设计模式之Builder模式

设计模式系列

创建型设计模式

Java 设计模式之单例模式

Java 设计模式之静态工厂方法模式

Java 设计模式之工厂方法模式

Java 设计模式之抽象工厂模式

Java 设计模式之Builder模式

Java 设计模式之静态工厂、工厂方法、抽象工厂和 Builder 模式的区别

结构型设计模式

Java 设计模式之代理模式

Java 设计模式之外观模式

前言

设计模式系列迎来了第五讲,我们来聊一聊 Builder 模式吧。

Builder 模式翻译为 建造者模式,又称生成器模式,是 GOF 提出的 23 种设计模式之一,类型属于 “创建型设计模式”。


定义

将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。

UML类图

UML 类图

图 1    UML 类图



大家仔细看 UML 类图,有没有觉得很奇怪:

怎么多了一个 Director 角色?

Builder 变成了 抽象类,另有一个具体的实现类 ConcreteBuilder ,好像跟我们平常直接使用的 Builder 不大一样。


这种被称为 Builder 的经典形式,我们来解释一下:

1、Product:具体的产品;

2、Builder:抽象的 Builder 类,规范产品的构建,一般由子类实现;

这就实现了 Builder(复杂对象的构建)和 Product(表示)的分离。

3、ConcreteBuilder:具体的 Builder 类,继承于抽象 Builder 类,实现了产品具体的构建过程,并返回一个组建好的对象;

由于可以有不同的 Builder 实现类 ConcreteBuilder,就 “使得同样的构建过程可以创建不同的表示”

4、Director:导演类,负责安排构建。


下面我们还是以 “月饼” 为例,结合代码理解一下这种模式。

经典形式

UML类图

还是先来看下经典形式示例的 UML 图,实际上就是对上述图 1 的具体化,如图 2 。

在这里插入图片描述

图 2    “经典形式” 示例的 UML 类图


程序代码


1、产品类 Mooncakes 就是简单的 Bean 类,即产品对象的 表示


程序清单 1     月饼 Bean 类 Mooncakes
public class Mooncakes{
    
    private String wrapper;
    private String filling;

    public Mooncakes setWrapper(String mWrapper){
        this.wrapper = mWrapper;
        return this;
    }

    public String getWrapper(){
        return wrapper;
    }

    public Mooncakes setFilling(String filling){
        this.filling = filling;
        return this;
    }

    public String getFilling(){
        return filling;
    }

}

2、构造器抽象类 Builder 规范了 产品对象的构建过程


程序清单 2     构造器抽象类 Builder
public abstract class Builder{
    
    // 构建月饼皮
    abstract Builder setWrapper(String mWrapper);

    // 构建月饼馅
    abstract Builder setFilling(String mFilling);

    // 完成月饼构建
    abstract Mooncakes build();
    
}

3、具体的构造器类 BeansandBuilder 实现了 产品对象具体的构建过程


程序清单 3     构造器实现类 BeansandBuilder
public class BeansandBuilder extends Builder {

    private Mooncakes mMooncakes = new Mooncakes();

    @Override
    Builder setWrapper(String mWrapper) {
        mMooncakes.setWrapper(mWrapper);
        System.out.println("月饼皮:" + mWrapper);
        return this;
    }

    @Override
    Builder setFilling(String mFilling) {
        mMooncakes.setFilling(mFilling);
        System.out.println("月饼馅:" + mFilling);
        return this;
    }

    @Override
    Mooncakes build() {
        System.out.println("月饼做好了");
        return mMooncakes;
    }

}

4、导演类 Director 负责统一管理产品的构建。


程序清单 4     导演类 Director
public class Director {

    private Builder mBuilder = null;

    // 实例化时设定构造器
    public Director(Builder builder) {
        this.mBuilder = builder;
    }

    // 开始构造产品
    public Mooncakes construct(String mWrapper, String mFilling) {
        return mBuilder.setWrapper(mWrapper).setFilling(mFilling).build();
    }
    
}

5、调用方使用 Director 构建产品,要在 Director 的构造方法注入构建器。


程序清单 5     调用方 Main
public class Main{

    public static void main(String[] args) {
        // 创建构建器器
        Builder beansandBuilder = new BeansandBuilder();
        // 注入构建器,创建导演类
        Director mDirector = new Director(beansandBuilder);
        // 开始构建产品
        mDirector.construct("金黄色的皮", "红豆沙的馅");
    }
    
}

简化形式

大家也都发现了,我们通常用的 Builder 不同于上文的经典形式,会对其简化,将 DirectorBuilderConcreteBuilder 简化为一个类 Builder,由 Builder 负责构建过程,将之与产品的表示分离。


我们还是通过一个示例帮助理解。

UML类图

简化形式的 UML 图

图 3    “简化形式” 示例的 UML 类图

解释一下这个 UML 类图:

1、产品类 Mooncakes 与经典形式一样,不再赘述;

2、MooncakesManager 是提供的一个管理类,Builder 是其内部构建类。通过 BuilderMooncakesManager 进行初始化配置及实例化,之后通过 MooncakesManager 实例生成产品。

程序代码

产品类 Mooncakes 与经典形式一样,不再重述代码。

我们来看下 MooncakesManager 代码,结合上面的解释进行理解。

程序清单 6     管理类 MooncakesManager
public class MooncakesManager{

    private Builder mBuilder = null;

    // 私有化构造,要通过Builder.build()得到实例
    private MooncakesManager(Builder mBuilder){
        this.mBuilder = mBuilder;
    }

    // 生产产品
    public Mooncakes create(){
        Mooncakes mooncakes = new Mooncakes();
        mooncakes.setWrapper(mBuilder.wrapper).setFilling(mBuilder.filling);
        return mooncakes;
    }

    /**
     * 构建器,用于管理类的初始化配置及生成管理类实例
     */
    public static class Builder{

        private String wrapper, filling;

        public Builder setWrapper(String wrapper){
            this.wrapper = wrapper;
            return this;
        }

        public Builder setFilling(String filling){
            this.filling = filling;
            return this;
        }

        // 构建得到管理类
        public MooncakesManager build(){
            return new MooncakesManager(this);
        }

    }

}

再来看下调用方是怎样调用的。

程序清单 7     调用方 Main
public class Main{

    public static void main(String[] args) {
        MooncakesManager.Builder builder = new MooncakesManager.Builder();
        builder.setWrapper("金黄色的皮").setFilling("红豆沙的馅").build().create();
    }
    
}

总结

Builder 模式比较常见,比如 Android 开发者熟悉的 AlertDialog.Builder ,还有一些第三方库也常用 Builder 模式(比如我的开源库 AppUpdate),大家可以看下他们的源码,基本都是上文所述的简化形式的 Builder 模式。

Builder 最重要的作用正如定义所说,为了将复杂对象的构建与表示相隔离,其 应用场景 具体来说可有以下几种情况:

1、要构建的对象比较复杂,比如参数很多,可定义项很多等;

2、要构建的对象,当构建过程的执行步骤不同,会产生不同的结果时;

3、要构建的对象,当选择的零部件不同时,会产生不同的结果时等。

要特别指出的是,Builder 模式常用于构建初始化时的配置项,配置项构建后,就可以生成相应的产品了。

本讲的示例源码已经放在 Gihub 上:BuilderPattern

感谢

  • 《Android源码设计模式解析与实战》 何红辉 关爱民
  • 《Android进阶之光》 刘望舒
  • 在线绘图网站 ProcessOn
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值