定义

建造者模式用来封装一个产品的构造过程,并允许按步骤来构造。

建造者模式的实现

建造者模式可以将对象构建过程隐藏在内部实现中,对外只提供一些构建步骤。

下面是关于建造者模式的类图

通常我们为了创建一个产品对象(Product),只需要客户端依赖抽象建造者,客户端与建造者间可以采用组合,具体的建造者与具体产品间也可以采用组合。

Jdk中的建造者

在日常开发中涉及字符串拼接操作经常会使用StringBuilder类。

StringBuilder sb = new StringBuilder();
sb.append("hello").append("world");
return sb.toString();

翻源码会发现StringBuilder继承自抽象类AbstractStringBuilder,而这个抽象类有两个实现,分别是加了对象锁的StringBuffer和无锁的StringBuilder,一个是线程安全的,另一个无法保证线程安全。

在《阿里巴巴Java开发手册》中也推荐使用StringBuilder进行字符串拼接。

【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。
说明:反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,然后进行 append 操作,最后通过 toString 方法返回 String 对象,造成内存资源浪费。

Effective Java 中的建造者(构建器)

在《Effective Java》书中的第2条就说明:当遇到多个构造器参数时可以考虑使用构建器

由于工厂模式与构造器不能够很好的扩展大量的可选参数。所以当类中存在大量的可选参数时,应该考虑使用构建器。

构建器模式让客户端利用所有必要参数调用构建器,得到一个builder对象,然后客户端在builder对象上调用类似于setter的方法,来设置每个相关的可选参数。最后,客户端调用无参的builder方法来生成不可变的对象。

下面示例来自《Effective Java》:

public class Product{
    private final int partA;
    private final int partB;
    private final int partC;

    public static class Builder{

        // 所有可选参数
        private final int partA = 0;
        private final int partB = 0;
        private final int partC = 0;

        public Builder(){

        }
        public Builder partA(int val){
            partA = val;
        }
        public Builder partB(int val){
            partB = val;
        }
        public Builder partC(int val){
            partC = val;
        }
        public Product build(){
            return new Product(this);
        }
    }

    private Product(Builder builder){
        partA = builder.partA;
        partB = builder.partB;
        partC = builder.partC;
    }
}

建造者模式的不足

虽然建造者模式在构建对象时是一个不错的选择,但是这个模式自身也存在不足。使用了建造器模式在创建对象之前必须先创建它的构建器。创建构造器会为创建对象带来一些额外的开销。

另外建造者模式无法与传统的类构造器或工厂模式做平滑切换,如果一开始没有使用建造者模式在后来才使用的话需要修改多处代码。因此,最好是一开始就使用建造者模式。

参考

  • 《Head First 设计模式》
最后修改日期: 2019年11月16日

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。