今天看了 《Effective Java》第二条: 遇到多个构造器参数时要考虑用构建器。做下学习笔记。
有时候一个类的域有很多,但并不是在创建时就需要的,可能必须的只有几个,那么我们会考虑构造器重载,例如一个商户有商户名,商户编码,所属代理商,法人姓名,身份证,地址等等,其中商户名和商户编码是必须的,那么只要提供一个这2个参数的构造器并且重载一些构造器即可,代码如下。
public class Merchant {
private String merchantName;
private String merchantCode;
private String agentCode;
private String corporateName;
private String identity;
private String addr;
public Merchant(String merchantName, String merchantCode) {
this.merchantName = merchantName;
this.merchantCode = merchantCode;
}
public Merchant(String merchantName, String merchantCode, String agentCode) {
super();
this.merchantName = merchantName;
this.merchantCode = merchantCode;
this.agentCode = agentCode;
}
public Merchant(String merchantName, String merchantCode, String agentCode, String corporateName) {
super();
this.merchantName = merchantName;
this.merchantCode = merchantCode;
this.agentCode = agentCode;
this.corporateName = corporateName;
}
public Merchant(String merchantName, String merchantCode, String agentCode, String corporateName, String identity) {
super();
this.merchantName = merchantName;
this.merchantCode = merchantCode;
this.agentCode = agentCode;
this.corporateName = corporateName;
this.identity = identity;
}
public Merchant(String merchantName, String merchantCode, String agentCode, String corporateName, String identity,
String addr) {
super();
this.merchantName = merchantName;
this.merchantCode = merchantCode;
this.agentCode = agentCode;
this.corporateName = corporateName;
this.identity = identity;
this.addr = addr;
}
}
很明显,这里才6个域,如果有很多呢,很不方便,于是我们可以采用javabean的方式,现在也大多使用框架开发,也都是JavaBean的方式,那么不管多少个域,只要提供set、get方法,然后再提供一个无参构造器就行了,如下:
public class Merchant {
private String merchantName;
private String merchantCode;
private String agentCode;
private String corporateName;
private String identity;
private String addr;
public String getMerchantName() {
return merchantName;
}
public void setMerchantName(String merchantName) {
this.merchantName = merchantName;
}
public String getMerchantCode() {
return merchantCode;
}
public void setMerchantCode(String merchantCode) {
this.merchantCode = merchantCode;
}
public String getAgentCode() {
return agentCode;
}
public void setAgentCode(String agentCode) {
this.agentCode = agentCode;
}
public String getCorporateName() {
return corporateName;
}
public void setCorporateName(String corporateName) {
this.corporateName = corporateName;
}
public String getIdentity() {
return identity;
}
public void setIdentity(String identity) {
this.identity = identity;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
}
这是我们大多数时候使用的方式,书中指出了这种方式的缺点:因为构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态,类无法仅仅通过检验构造器参数的有效性来保证一致性。试图使用处于不一致状态的对象,将会导致失败,这种失败与包含错误的代码大相径庭,因此调试起来十分困难。另外,JavaBean模式阻止了把类做成不可变的可能,就需要程序员付出额外的努力来确保他的线程安全。
这部分我现在还不是很好的理解。
除了重载构造器和JavaBean模式外,还可以使用构建器的方式,如下:
public class Merchant {
private String merchantName;
private String merchantCode;
private String agentCode;
private String corporateName;
private String identity;
private String addr;
public static class Builder {
private String merchantName;
private String merchantCode;
private String agentCode;
private String corporateName;
private String identity;
private String addr;
public Builder(String mchName, String code) {
this.merchantName = mchName;
this.merchantCode = code;
}
public Builder agent(String agentCode) {
this.agentCode = agentCode;
return this;
}
public Builder corporate(String corporateName) {
this.corporateName = corporateName;
return this;
}
public Builder identity(String identity) {
this.identity = identity;
return this;
}
public Builder address(String addr) {
this.addr = addr;
return this;
}
public Merchant build() {
return new Merchant(this);
}
}
private Merchant(Builder builder) {
this.addr = builder.addr;
this.identity = builder.identity;
this.corporateName = builder.corporateName;
this.agentCode = builder.agentCode;
}
}
使用构建器的话就很灵活了,采用链式调用,如:
Merchant mer = new Merchant.Builder("测试商户", "M0001").agent("A0223").address("北京西直门外大街").build();
构建器优点:
1.有多个可变参数,构造器只能有一个;
2.比JavaBean安全;
缺点:
1.创建对象必须先创建他的构建器;
2.代码比重载构造器更冗长。
现在对此的理解还不是很深入,但算是多一种思路吧,以后有新的想法再来补充。