多个构造器时考虑用构建器:javaBeans模式可能处于不一致性 ------- Effective java source

在 Effective java中有看到介绍遇到多个构造器时考虑用构建器中有一个javaBeans模式致命缺点是不一致性,同时与之相关带来线程安全问题;本篇立足于Effective java来进行清晰的探讨;

1. 重叠构造

  • 在java中比较基础的是构造器来初始化,作为程序员习惯使用重叠构造模式,当传入一个参数的构造时候,第一个有一个必选参数,第二个有一个必选参数和一个可选参数,第三个有两个可选参数….通过重叠构造,关联所有的多参构造,实现关联;如下代码:
public class Person {

    private String name;
    private String age;
    private String sex;
    private String country;
    private String edc;

    public Person(String name) {
        this(name,null);
    }

    public Person(String name, String age) {
        this(name,age,null);
    }

    public Person(String name, String age, String sex) {
        this(name,age,sex,null);
    }


    public Person(String name, String age, String sex, String country) {
        this(name,age,sex,country,null);
    }


    public Person(String name, String age, String sex, String country, String edc) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.country = country;
        this.edc = edc;
    }
}
  • 但是有一个问题,一个参数,两个参数,三个参数,使用其构造传参会比较明确,但是对于多参的构造,会涉及到参数顺序的问题,有时候会传参出错,而且参数太多,难以阅读,对参数的把控性不高,不利于程序的阅读;

2. javabeans 模式

  • 出于程序可读性以及参数的可控性的考虑我们会是会用javabean来进行类实例化和属性的赋值:
public class Person impletement Serializable{

    private String name;
    private String age;
    private String sex;
    private String country;
    private String edc;
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getEdc() {
        return edc;
    }

    public void setEdc(String edc) {
        this.edc = edc;
    }
}
  • 在使用javabean的时候,尤其是多线程时候,获取同一个javabean(可以通过序列/反序列获取),那么下面模拟一个场景:
    线程A: 获取person,对其name age sex 就行set操作
    同样线程B: 获取person,对其进行get操作
    这时候会出现一种情况,在线程A中没有set完毕,线程B 就开始取相应的属性
那么就会造成javabean出于不一致的状态;随之相关就是线程安全的问题,所以javabean作为数据的一个填充,姚进行必要的保护性拷贝(这里不做解释)

3. 建造者(builder) 模式

  • 直接来看代码
public class Person implements Serializable{

    private String name;
    private String age;
    private String sex;
    private String country;
    private String edc;

    public Person(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
        this.sex = builder.sex;
        this.country = builder.country;
        this.edc = builder.edc;
    }


    public static class Builder{


        private String name;
        private String age;
        private String sex;
        private String country;
        private String edc;

        public Builder setName(String name) {
            this.name = name;
            return this;
        }

        public Builder setAge(String age) {
            this.age = age;
            return this;
        }

        public Builder setSex(String sex) {
            this.sex = sex;
            return this;
        }

        public Builder setCountry(String country) {
            this.country = country;
            return this;
        }

        public Builder setEdc(String edc) {
            this.edc = edc;
            return this;
        }


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


}
  • 在建造者模式中,提供一个辅助的静态建造器builder,可以在里面set Person的属性,与javaBean不同的是,建造者是先set,在通过build实例化person,这样既可以提高代码的阅读性,也可以防止对象没有实例化,就被调用;不会造成不一致性,同时解决了javabean模式的线程安全问题;

作为一个java的工程师,应当从基础入手,深入理解面向对象,与君共勉,感谢阅读 ^.^

猜你喜欢

转载自blog.csdn.net/soullines/article/details/80240814