美文网首页
第二条:当遇到构造器有多个参数时要考虑使用构建器

第二条:当遇到构造器有多个参数时要考虑使用构建器

作者: Js_Gavin | 来源:发表于2020-11-29 14:36 被阅读0次

    静态工厂方法和构造器都有一个共同的缺点,都不能很好的扩展到大量的参数。

    对于有多个参数时,我们一向习惯使用重叠构造器模式,在这种情况下,提供一个必填参数的构造器,第二个构造器带有一个可选参数,第三个构造器带有两个可选参数,以此类推,最后一个构造器包含所有参数:举个粒子:

    public class Demo{
        private String var1;
        private String var2;
        private String var3;
        public Demo(String var1){
            this(var1,"");  
        }
        public Demo(String var1,String var2){
            this(var1,var2,"");
        }
        public Demo(String var1,String var2,String var3){
            this.var1 = var1;
            this.var2 = var2;
            this.var3 = var3;
        }
    }
    
    public class Main{
        public static void main(String[] args){
            Demo demo = new Demo("setVar1");
            demo = new Demo("setVar1","setVar2");
            demo = new Demo("setVar1","setVar2","setVar3");
        }
    }
    

    如果仅仅是这几个参数还不算大问题,但是随着参数的增加,很快就会变得失去控制。而且随着参数的增加,必须仔细的数着这些参数来确保传入值的顺序正确。如果出现顺序的颠倒,编译器可能不会报错,但是程序运行的结果却却可能天差地别,甚至会出现异常。

    还有一种方式是通过JavaBean的setter方法来为每个值单独设值。

    public class Demo{
        private String var1;
        private String var2;
        private String var3;
        public Demo(){
        }
        public Demo(String var1){
            this(var1,"");  
        }
        public Demo(String var1,String var2){
            this(var1,var2,"");
        }
        public Demo(String var1,String var2,String var3){
            this.var1 = var1;
            this.var2 = var2;
            this.var3 = var3;
        }
        public void setVar1(String var1){
            this.var1 = var1
        }
        public void setVar2(String var2){
            this.var2 = var2
        }
        public void setVar3(String var2){
            this.var2 = var2
        }
    }
    
    public class Main{
        public static void main(String[] args){
            Demo demo = new Demo();
            demo.setVar1("setVar1");
            demo.setVar2("setVar2");
            demo.setVar3("setVar3");
        }
    }
    

    这种模式在构造过程中,在多线程的情况下无法保证数据的一致性,需要符出额外的努力来确保线程安全。

    有一种方案可以比较好的解决以上问题,既能保存重叠构造器模式的安全性,又能保证可读性,这就是建造者模式的一种体现,这种方式不直接生成对象,而是利用必要的参数调用构造器或者静态工厂方法,得到一个Builder对象,然后在Builder对象中调用类似于setter的方法,来设置可选参数,最后,调用无参的build方法来生成目标对象。build通常是他构建类的成员静态类。举个栗子:

    public class Demo{
        private String name;
        private int age;
        private Date time;
        private String other;
        public static class Builder{
            private String name;
            private int age;
            private Date time;
            private String other;
            public Builder(String name,int age){ // 静态成员类
                this.name = name;
                this.age = age;
            }
            public Builder time(Date time){
                this.time = time;
                return this;
            }
            public Builder other(String other){
                this.other = other; 
                return this; 
            }
             public Demo build(){
                  return new Demo(this);
            }
        }
        private Demo(Builder builder){
            this.name = builder.name;
            this.age = builder.age;
            this.time = builder.time;
            this.other = builder.other;
        }
    }
    
    public class Main{
        public static void main(String[] args){
            Demo demo = new Demo.Builder("xiaowu",1).time(new Date()).other("love java").build();
        }
    }
    

    与构造器相比,builder的优势在于,可以有多个可变参数,因为bulidre利用单独的方法来设置每一个参数,此外,构建器可以将多次调用某一个方法的参数集中到一个集合中。

    builder的模式也有不足之处,为了创建对象,需要先创建构建器,虽然创建builder的开销在实践中不是很明显,但是在某些十分注重性能的情况下,可能就会有问题,而且builder比重叠构造器模式更加沉长,所以建议只有当参数超过4个及以上,或者将来可能需要更多的参数,就可以考虑使用builder模式。

    简而言之,如果类的构造器或者静态工厂中有多个参数,设计这种类时,builder模式是一种不错的选择,与构造器相比,使代码更加易于阅读和编写,同时也比JavaBean模式更加安全。

    相关文章

      网友评论

          本文标题:第二条:当遇到构造器有多个参数时要考虑使用构建器

          本文链接:https://www.haomeiwen.com/subject/dfpwiktx.html