Android设计模式之Builder模式

Builder设计模式


定义:

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

参与者:

  • Product:被构建的复杂对象,ConcreteBuilder用来创建该对象的内部表示,并定义它的装配过程。
  • Builder:抽象接口,用来定义创建Product对象的各个组成部件操作
  • ConcreteBuilder:Builder接口的具体实现。可以定义多个,是实际构建Product对象的地方,同时会提供一个返回Product的接口
  • Director:Builder接口的构造者和使用者

Builder模式的变种

目的:

减少对象创建过程中引入多个重载构造函数,可选参数以及setters函数过度使用导致的不必要的复杂性。

例子讲解:

public class User {
    private final String mFirstName;//必选
    private final String mLastName;//必选
    private final String mGender;//可选属性
    private final int mAge;//可选属性
    private final String mPhoneNo;//可选属性

    private User(UserBuilder userBuilder) {
        mFirstName = userBuilder.firstName;
        mLastName = userBuilder.lastName;
        mGender = userBuilder.gender;
        mAge = userBuilder.age;
        mPhoneNo = userBuilder.phoneNo;
    }

    public String getmFirstName() {
        return mFirstName;
    }

    public String getmLastName() {
        return mLastName;
    }

    public String getmGender() {
        return mGender;
    }

    public int getmAge() {
        return mAge;
    }

    public String getmPhoneNo() {
        return mPhoneNo;
    }

    public static class UserBuilder{
        private final String firstName;
        private final String lastName;
        private String gender;
        private int age;
        private String phoneNo;
        public UserBuilder(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }
        public UserBuilder gender(String gender) {
            this.gender = gender;
            return this;
        }
        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }
        public UserBuilder phoneNo(String phoneNo) {
            this.phoneNo = phoneNo;
            return this;
        }
        public User build() {
            return new User(this);
        }
    }
}

//使用
//这样子就构建了一个User对象,当然,后面的属性也可以选填或者不填。
       User user = new User.UserBuilder("黄","小明").age(15).gender("qqq").phoneNo("456789").build();

优点

  • 减少对象创建过程中引入多个重载构造函数,可选参数以及setters函数过度使用导致的不必要的复杂性。
  • 代码容易维护,容易使用。后续想要添加属性,直接添加一个相对应的属性和其方法即可。
  • 如果采取无参构造函数,接着使用set来设置属性,那么User类的实例状态不连续。直到第五个set函数被调用时,该类的实例才具有完整连续的状态,也就意味着类调用者会看到该类实例的不连续状态。
  • 设定final修饰属性值不可变。

缺点

  • 需要编写很多的样板代码,需要在内部类UserBuilder中重复外部类User的属性定义。

变种Builder模式的自动化生成

在AndroidStudio中,安装名为InnerBuilder的插件。
Android设计模式之Builder模式

编写User类代码的时候,只需要把属性名确定下来,然后单击鼠标右键,打开Generate菜单,选择Builder按钮,在配置对话框中进行相关配置的勾选即可。

举个例子


public class Person {
    private final String mLastName;//必填
    private final String mFirstName;//必填
    private int mHeight;//选填
    private int mBodyWeight;//选填
}

Android设计模式之Builder模式

第一个打勾的意思是:生成final字段的构造器方法。
如果不打勾,那么生成的代码就和我们上面的User类代码一致。

生成后的代码:


public class Person {
    private final String mLastName;//必填
    private final String mFirstName;//必填
    private int mHeight;//选填
    private int mBodyWeight;//选填

    private Person(Builder builder) {
        mLastName = builder.mLastName;
        mFirstName = builder.mFirstName;
        mHeight = builder.mHeight;
        mBodyWeight = builder.mBodyWeight;
    }

    public static final class Builder {
        private String mLastName;
        private String mFirstName;
        private int mHeight;
        private int mBodyWeight;

        public Builder() {
        }

        public Builder mLastName(String val) {
            mLastName = val;
            return this;
        }

        public Builder mFirstName(String val) {
            mFirstName = val;
            return this;
        }

        public Builder mHeight(int val) {
            mHeight = val;
            return this;
        }

        public Builder mBodyWeight(int val) {
            mBodyWeight = val;
            return this;
        }

        public Person build() {
            return new Person(this);
        }
    }
}

利用工具来进行类的Builder模式构建真的很快,效率是杠杠的。

变种Builder模式的应用

1. Android系统对话框AlertDialog的使用

AlertDialog alertDialog = new AlertDialog.Builder(this)
                .setTitle("对话框标题")
                .setMessage("对话框内容")
                .setIcon(R.drawable.ic_launcher_background)
                .create();
        alertDialog.show();

2. 网络请求框架OkHttp的请求封装

这个大家可以阅读下OkHttp3的源码,里面大量应用了Builder设计模式。
Request:
Android设计模式之Builder模式
Android设计模式之Builder模式

OkHttpClient:
Android设计模式之Builder模式

所以,这都体现出Builder设计模式的好处:
将一个复杂对象与它的表示分离,使得同样的构建过程可以创建不同的表示。
减少对象创建过程中引入多个重载构造函数,可选参数以及setters函数过度使用导致的不必要的复杂性。


参考:《Android高级进阶》