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的插件。
编写User类代码的时候,只需要把属性名确定下来,然后单击鼠标右键,打开Generate菜单,选择Builder按钮,在配置对话框中进行相关配置的勾选即可。
举个例子
public class Person {
private final String mLastName;//必填
private final String mFirstName;//必填
private int mHeight;//选填
private int mBodyWeight;//选填
}
第一个打勾的意思是:生成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:
OkHttpClient:
所以,这都体现出Builder设计模式的好处:
将一个复杂对象与它的表示分离,使得同样的构建过程可以创建不同的表示。
减少对象创建过程中引入多个重载构造函数,可选参数以及setters函数过度使用导致的不必要的复杂性。
参考:《Android高级进阶》