遇到多个构造器参数时考虑用构建器

静态工厂方法和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数。在android开发中有时需要自定义Dialog类,这些Dialog有两个域是必需的:context,message,还有一些域是可选的:title,positiveButton,negativeButton,imageView,positiveClickListener,negativeClickListener等。
对于这样的类,应用哪种构造器或者静态方法来编写呢?首先想到的可能是重叠构造器模式,在这种模式下,你提供第一个只有必要参数的构造器,第二个构造器只有一个可选参数,第三个有两个可选参数,以此类推,最后一个构造期包含所有可选参数。为简单起见,下面实例只展示三个可选项:

public class MyDialog {
    private Context m_context;
    private String message;

    private String title;
    private String positiveButtonText;
    private String negativeButtonText;


    public MyDialog(Context context, String message) {
        m_context = context;
        this.message = message;
    }

    public MyDialog(Context context, String title, String message) {
        m_context = context;
        this.title = title;
        this.message = message;
    }

    public MyDialog(Context context, String title, String message, String positiveButtonText) {
        m_context = context;
        this.title = title;
        this.message = message;
        this.positiveButtonText = positiveButtonText;
    }

    public MyDialog(Context context, String message, String title, String positiveButtonText, String negativeButtonText) {
        m_context = context;
        this.message = message;
        this.title = title;
        this.positiveButtonText = positiveButtonText;
        this.negativeButtonText = negativeButtonText;
    }
}

然后其他地方可以这样调用:

MyDialog dialog=new MyDialog(this,"message","title","positiveText","negativeText");

1、这样就会产生很多的构造器,增加代码量。2、假如我只需要negativeButtonText,就只能使用最后一个构造器,此时positiveButtonText参数也会传进来,但是此时我并不需要positiveButtonText参数呀,如果可选参数很多的话,这样的冗余参数会更多。3、这样也很难分清第n个参数到底代表的是什么含义,需要回过头来仔细看下构造器每个参数代表啥意思,如果不小心颠倒了其中两个参数的顺序,编译器不会出错,但是得到的效果却不是我们想要的。随着参数数目的增加,它很快就失去了控制。

遇到许多构造器参数的时候,还有第二种代替方法,即JavaBeans模式,在这种模式下,调用一个必需参数构造器来创建对象,然后调用setter方法来设置每个可选的参数。

public class MyDialog {
    private Context m_context;
    private String message;

    private String title;
    private String positiveButtonText;
    private String negativeButtonText;


    public MyDialog(Context context, String message) {
        m_context = context;
        this.message = message;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setPositiveButtonText(String positiveButtonText) {
        this.positiveButtonText = positiveButtonText;
    }

    public void setNegativeButtonText(String negativeButtonText) {
        this.negativeButtonText = negativeButtonText;
    }
}

此时可以这样调用:

MyDialog dialog=new MyDialog(this,"message");
        dialog.setTitle("title");
        dialog.setPositiveButtonText("positiveText");
        dialog.setNegativeButtonText("negativeText");

这种模式弥补了重叠构造器模式的不足,并且代码读写也更加容易,妈妈再也不用担心我把参数搞错了。

遗憾的是,JavaBeans模式自身有着严重的缺点。因为构造器被分到几个调用中,在构造过程中JavaBean可能处于不一致的状态。试图使用不一致状态的对象,将会导致失败,这种失败与包含错误的代码大相径庭,调试起来十分困难,同时,JavaBeans模式阻止了把类变成不可变的可能,这就使得程序员付出额外的努力来确保它的线程安全。

主角出来啦,既可以保证像重叠构造器模式那样的安全性,也能保证像JavaBeans模式那么好的可读性,这就是Builder模式。不直接生成想要的对象,而是让客户端利用所有必要的参数构造器,得到一个builder对象。然后客户端在builder对象上调用类似setter的方法,来设置可选参数。最后,客户端调用无参的build方法生成不可变对象。这个builder是它构建的类的静态成员类。

public class MyDialog {
    private Context m_context;
    private String message;

    private String title;
    private String positiveButtonText;
    private String negativeButtonText;


    public static class Builder{
        private Context m_context;
        private String message;

        private String title;
        private String positiveButtonText;
        private String negativeButtonText;

        public Builder(Context context, String message) {
            m_context = context;
            this.message = message;
        }

        public Builder setTitle(String title) {
            this.title = title;
            return this;
        }

        public Builder setPositiveButtonText(String positiveButtonText) {
            this.positiveButtonText = positiveButtonText;
            return this;
        }

        public Builder setNegativeButtonText(String negativeButtonText) {
            this.negativeButtonText = negativeButtonText;
            return this;
        }

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

    }

    private MyDialog(Builder builder){
        m_context = builder.m_context;
        this.message = builder.message;
        this.title = builder.title;
        this.positiveButtonText = builder.positiveButtonText;
        this.negativeButtonText = builder.negativeButtonText;
    }

}

此时可以这样调用:

MyDialog dialog = new MyDialog.Builder(this, "mesage")
                .setTitle("title")
                .setPositiveButtonText("positiveText")
                .setNegativeButtonText("negativeText")
                .build();

注意:实际开发中android dialog需要添加布局以及其他业务逻辑,上面的MyDialog 只是展示其核心用法。

猜你喜欢

转载自blog.csdn.net/u013795543/article/details/73681481