构造模式(Builder模式)
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示、
概念:比较抽象的,让大家很难理解的,如果简单从这个一个概念就搞懂了这个模式的话,那就不用费力的去查资料整理后边的东西了。
作用:Builder模式的目的在于减少对象创建过程中引用的多个重载构造方法、可选参数和setters过度使用导致的不必要的复杂性。
通过一个例子来引出Build模式。假设有一个Student类,该类的一些属性可以为null,可以通过这个类来构架一大批学生
public class Student {
private String mParentName;//父母的名字
private String mParentTel;//父母的电话
private String mHomeAddress;//家庭地址
private String mName;//名字
private int mAge;//年龄
private String mGender;//性别
public String getmParentName() {
return mParentName;
}
public void setmParentName(String mParentName) {
this.mParentName = mParentName;
}
public String getmParentTel() {
return mParentTel;
}
public void setmParentTel(String mParentTel) {
this.mParentTel = mParentTel;
}
public String getmHomeAddress() {
return mHomeAddress;
}
public void setmHomeAddress(String mHomeAddress) {
this.mHomeAddress = mHomeAddress;
}
public String getmName() {
return mName;
}
public void setmName(String mName) {
this.mName = mName;
}
public int getmAge() {
return mAge;
}
public void setmAge(int mAge) {
this.mAge = mAge;
}
public String getmGender() {
return mGender;
}
public void setmGender(String mGender) {
this.mGender = mGender;
}
}
然后为了方便,我们可能会写这么一个构造函数来传属性
public Student(String mParentName, String mParentTel, String mHomeAddress, String mName, int mAge, String mGender) {
this.mParentName = mParentName;
this.mParentTel = mParentTel;
this.mHomeAddress = mHomeAddress;
this.mName = mName;
this.mAge = mAge;
this.mGender = mGender;
}
或者为了更方便还会写一个空的构造函数
public Student (){}
有时候还会比较懒,只传入某些参数,又会来写这些构造函数
public Student(String mParentName, String mParentTel, String mName) {
this.mParentName = mParentName;
this.mParentTel = mParentTel;
this.mName = mName;
}
public Student(String mName) {
this.mName = mName;
}
于是就可以来创建各种需要的类的对象。
Student s1 = new Student();
Student s2 = new Student("name");
Student s3 = new Student("mParentName","mParentTel","mName");
Student s4 = new Student("mParentName","mParentTel","mHomeAddress","mName","mAge","mGender");
其实这种写法的坏处在你写的过程中就该想到了,既然就是一个创建对象的过程,怎么这么繁琐,并且构造函数参数过多或不同,其他人创建对象的时候怎么知道各个参数代表什么意思呢,这个时候我们为了代码的可读性,就可以用一下Builder模式了。给Student类添加一个静态Builder类,然后修改Student的构造函数。
public class Student {
private String mParentName;//父母的名字 必写
private String mParentTel;//父母的电话 必写
private String mHomeAddress;//家庭地址 必写
private String mName;//名字
private int mAge;//年龄
private String mGender;//性别
private Student (Builder builder){
mParentName = builder.mParentName;
mParentTel = builder.mParentTel;
mName = builder.mName;
mAge = builder.mAge;
mHomeAddress = builder.mHomeAddress;
mGender = builder.mGender;
}
public String getmParentName() {
return mParentName;
}
public void setmParentName(String mParentName) {
this.mParentName = mParentName;
}
public String getmParentTel() {
return mParentTel;
}
public void setmParentTel(String mParentTel) {
this.mParentTel = mParentTel;
}
public String getmName() {
return mName;
}
public void setmName(String mName) {
this.mName = mName;
}
public int getmAge() {
return mAge;
}
public void setmAge(int mAge) {
this.mAge = mAge;
}
public String getmHomeAddress() {
return mHomeAddress;
}
public void setmHomeAddress(String mHomeAddress) {
this.mHomeAddress = mHomeAddress;
}
public String getmGender() {
return mGender;
}
public void setmGender(String mGender) {
this.mGender = mGender;
}
public static final class Builder{
private String mParentName;//父母的名字
private String mParentTel;//父母的电话
private String mName;//名字
private int mAge;//年龄
private String mHomeAddress;//家庭地址
private String mGender;//性别
public Builder (String parentName ,String parentTel){//说明这两个参数是必填写的,当然你也可以设置成不必填写(看需求吧)
mParentName = parentName;
mParentTel = parentTel;
}
public Builder setName(String studentName){
mName = studentName;
return this;
}
public Builder setAge(int age){
mAge = age;
return this;
}
public Builder setHomeAddress(String homeAddress){
mHomeAddress = homeAddress;
return this;
}
public Builder setGender(String gender){
mGender = gender;
return this;
}
public Student build(){
return new Student(this);
}
}
}
从上面代码我们可以看到我们在Builder类中定义了一份跟Student类一样的属性,通过一系列的成员函数进行赋值,但是返回的都是this,最后提供了一个build函数来创建Student对象,对应的在Student的构造函数中,传入了Builder对象,然后依次对自己的成员变量进行赋值。此外,Builder类也有一个要传参的构造方法,其参数是必须的传入(这几个参数也就是说Student类里必须赋值的),当然也可以构造一个空的构造方法。Builder的成员函数返回的都是this的另一个作用就是让他支持链式调用,使代码可读性大大增强。
那么我们就可以这样创建Student对象。
public class TestJava {
public static void main(String agr[]){
Student student = new Student.Builder("卢家长","13811112222")
.setName("卢一")
.setAge(10)
.setHomeAddress("夏郢")
.setGender("男")
.build();
System.out.println(student.getmParentName());
System.out.println(student.getmParentTel());
System.out.println(student.getmName());
System.out.println(student.getmAge());
System.out.println(student.getmHomeAddress());
Student.Builder builder = new Student.Builder("lu家长","13422221111");
Student stu = builder.setName("卢三")
.setHomeAddress("福田")
.build();
System.out.println("===========================");
System.out.println(stu.getmParentName());
System.out.println(stu.getmParentTel());
System.out.println(stu.getmName());
System.out.println(stu.getmAge());
System.out.println(stu.getmHomeAddress());
}
}
用Builder模式是不是简单又清楚,主要是在Student类不用大量构造不同的构造方法,根据需求赋值就可以了,并且容易维护,扩展性强。
Android中大量地方运用到了Builder模式,比如常见的对话框创建。
AlertDialog.Builder builder=new AlertDialog.Builder(this);
AlertDialog dialog=builder.setTitle("我就是用BUILDER模式的对话框")
.setIcon(android.R.drawable.ic_dialog)
.setView(R.layout.custom_view)
.setPositiveButton(R.string.positive, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setNegativeButton(R.string.negative, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.create();
dialog.show();
ImageLoader使用Builder设计模式
private void initImageLoader() {
ImageLoaderConfiguration.Builder config = new
ImageLoaderConfiguration.Builder(getContext());
config.threadPriority(Thread.NORM_PRIORITY - 2);
config.denyCacheImageMultipleSizesInMemory();
config.memoryCacheSize(5 * 1024 * 1024);// 5M
config.tasksProcessingOrder(QueueProcessingType.LIFO);
ImageLoader.getInstance().init(config.build());
}
Gson中的GsonBuilder也运用了Builder设计模式
GsonBuilder builder=new GsonBuilder();
Gson gson=builder.setPrettyPrinting()
.disableHtmlEscaping()
.generateNonExecutableJson()
.serializeNulls()
.create();
平时用得最多的网络框架OKHttp也运用了Builder设计模式
Request.Builder builder=new Request.Builder();
Request request=builder.addHeader("","")
.url("")
.post(body)
.build();
当你们在开发中注意过源代码亦或大量框架代码时,就会惊讶地发现里面也运用了Builder设计模式。
Android Studio自动生成变种Builder模式。如果你的Android Studio中没有安装InnerBuilder插件,则先去安装。
安装好后重启Android Studio,只需要把属性名确定下来,alt键+insert键,选择builder按钮即可(快捷键Alt+Shift+B)。
总结
-
在类中定义一个静态内部类Builder,内部成员变量跟外部一样。
-
如果某些成员变量是必传输值时,可以在Builder的构造方法中协带。反之可以不用构造方法。
-
Builder通过一系列方法给成员变量赋值,并返回当前对象(this)。
-
Builder类内部提供一个build方法方法或者create方法用于创建对应的外部类,该方法内部调用了外部类的一个私有化构造方法,该构造方法的参数就是内部类Builder。
-
外部类提供一个私有化的构造方法供内部类调用,在该构造函数中完成成员变量的赋值。
网友评论