Android知识

小点知识——构造模式(Builder模式)

2018-03-07  本文已影响75人  安仔夏天勤奋

构造模式(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)。

总结

  1. 在类中定义一个静态内部类Builder,内部成员变量跟外部一样。

  2. 如果某些成员变量是必传输值时,可以在Builder的构造方法中协带。反之可以不用构造方法。

  3. Builder通过一系列方法给成员变量赋值,并返回当前对象(this)。

  4. Builder类内部提供一个build方法方法或者create方法用于创建对应的外部类,该方法内部调用了外部类的一个私有化构造方法,该构造方法的参数就是内部类Builder。

  5. 外部类提供一个私有化的构造方法供内部类调用,在该构造函数中完成成员变量的赋值。

上一篇下一篇

猜你喜欢

热点阅读