什么是Builder模式

相信很多Android开发者都使用过形如下面的代码创建过dialog。

AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Title")
       .setMessage("message")
       .setCancelable(true);
AlertDialog dialog = builder.create();

可以看到一个dialog对象并不是通过new关键字传参来直接创建,而是通过一个中间变量builder来实现,通过不断的对builder设置参数,最后通过builder的一个方法来完成对对象的创建。这就是所谓的builder模式。

Builder模式的实现思路

因为不能通过new来创建,所以构造函数肯定是私有的,而builder类又要调用构造函数,所以builder类一定是要创建的主类的内部类。除此之外,由于是builder对象返回的主类对象,所以builder对象肯定持有一个主类的实例对象。之后便是各种set方法来对这个对象赋值,最后通过一个公共的方法返回该对象。

单例的实现方式

public class Product {
    private String attribute1;
    private String attribute2;
    private String attribute3;

    private Product() {

    }

    @Override
    public String toString() {
        return attribute1 + " " + attribute2 + " " + attribute3;
    }

    public static class Builder {
        private Product product = new Product();
        public void setAttribute1(String attribute1) {
            product.attribute1 = attribute1;
        }

        public void setAttribute2(String attribute2) {
            product.attribute2 = attribute2;
        }

        public void setAttribute3(String attribute3) {
            product.attribute3 = attribute3;
        }

        public Product build() {
            return product;
        }
    }
}

我们基本上按照上述思路实现了该代码,为了一会调试方便我加了一个toString方法。

可以看到我在这创建了一个product类,这个类有三个属性,可以是任意类型,为了方便我都给设置成了string。之后通过内部类builder的三个set方法去设置这三个值,通过create方法返回product对象。

在主类中写如下测试代码,可以看到如图的运行结果。

public class Main {
    public static void main(String[] args) {
        Product.Builder builder = new Product.Builder();
        builder.setAttribute1("属性1");
        builder.setAttribute2("属性2");
        builder.setAttribute3("属性3");
        Product product = builder.build();
        System.out.println(product.toString());
    }
}

但是这段代码比较繁琐,并没有实现像最开始介绍时创建dialog时那么方便,我们可以通过对代码进行修改来改正这个不方便的地方。

修改builder类的代码,令它的3个set方法都在赋值后返回它自身,这样就完成了。

    public static class Builder {
        private Product product = new Product();
        public Builder setAttribute1(String attribute1) {
            product.attribute1 = attribute1;
            return this;
        }

        public Builder setAttribute2(String attribute2) {
            product.attribute2 = attribute2;
            return this;
        }

        public Builder setAttribute3(String attribute3) {
            product.attribute3 = attribute3;
            return this;
        }

        public Product build() {
            return product;
        }
    }

主类测试运行结果和上面一样,就不贴图了。

        Product.Builder builder = new Product.Builder();
        Product product = builder.setAttribute1("属性1")
                .setAttribute2("属性2")
                .setAttribute3("属性3")
                .build();
        System.out.println(product.toString());

Builder模式的优缺点

优点

  • 良好的封装性(调用者不必知道主类的实现细节,只需要对自己关心的值进行设置)
  • 容易扩展(增加属性只需要对builder增加一个对应的方法即可)

缺点

  • 作为中间值产生的builder对象会消耗不必要的内存
收藏