在 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的工程师,应当从基础入手,深入理解面向对象,与君共勉,感谢阅读 ^.^