《effective java》读书笔记——遇到多个构造器参数时
2017-09-03 本文已影响26人
小小浪把_Dont_know拍
在日常工作中,业务场景会非常复杂。为了满足对应的业务场景,我们需要同时兼容多种情况。
业务背景
账号体系支持多种用户身份,对于这种需求,本应该生成一个全局唯一的id。但是由于原先的设计不太优雅,我们需要适配原先的业务场景。
- 手机号身份,这是内部注册的账号,buyerId。
- 其他app账号绑定,例如微信、qq、微博,fansType和fansId。
用户类
public class User {
private long buyerId;
private int fansType;
private long fansId;
public long getBuyerId() {
return buyerId;
}
public void setBuyerId(long buyerId) {
this.buyerId = buyerId;
}
public int getFansType() {
return fansType;
}
public void setFansType(int fansType) {
this.fansType = fansType;
}
public long getFansId() {
return fansId;
}
public void setFansId(long fansId) {
this.fansId = fansId;
}
}
问题:需要了解业务细节,没有规则约束,容易遗漏字段
多个构造器参数类
public class User {
private final long buyerId;
private final int fansType;
private final long fansId;
public User(long buyerId) {
this.buyerId = buyerId;
this.fansType = 0;
this.fansId = 0;
}
public User(int fansType, long fansId) {
this.buyerId = 0;
this.fansType = fansType;
this.fansId = fansId;
}
public User(long buyerId, int fansType, long fansId) {
this.buyerId = buyerId;
this.fansType = fansType;
this.fansId = fansId;
}
}
问题:构造方法太多,不利于后续维护
业务需求变化
产品说,我们需要支持匿名用户。构造器参数又得增加一倍,程序员的恶梦开始了。
用构建器改造
public class Builder {
private long buyerId;
private int fansType;
private long fansId;
public long getBuyerId() {
return buyerId;
}
public void setBuyerId(long buyerId) {
this.buyerId = buyerId;
}
public int getFansType() {
return fansType;
}
public void setFansType(int fansType) {
this.fansType = fansType;
}
public long getFansId() {
return fansId;
}
public void setFansId(long fansId) {
this.fansId = fansId;
}
public User build() {
if (buyerId == 0 && fansType == 0 && fansId == 0) {
throw new RuntimeException("please init user data");
}
if (fansId != 0 && fansType == 0) {
throw new RuntimeException("invalid fans type");
}
if (fansType != 0 && fansId == 0) {
throw new RuntimeException("invalid fans id");
}
return new User(this);
}
}
public class User {
private final long buyerId;
private final int fansType;
private final long fansId;
User(Builder builder) {
buyerId = builder.getBuyerId();
fansType = builder.getFansType();
fansId = builder.getFansId();
}
}
问题:不够内聚
内部类
public class User {
private final long buyerId;
private final int fansType;
private final long fansId;
private User(Builder builder) {
buyerId = builder.buyerId;
fansType = builder.fansType;
fansId = builder.fansId;
}
public static class Builder {
private long buyerId;
private int fansType;
private long fansId;
public Builder buyerId(long buyerId) {
this.buyerId = buyerId;
return this;
}
public Builder fansType(int fansType) {
this.fansType = fansType;
return this;
}
public Builder fansId(long fansId) {
this.fansId = fansId;
return this;
}
public User build() {
if (buyerId == 0 && fansType == 0 && fansId == 0) {
throw new RuntimeException("please init user data");
}
if (fansId != 0 && fansType == 0) {
throw new RuntimeException("invalid fans type");
}
if (fansType != 0 && fansId == 0) {
throw new RuntimeException("invalid fans id");
}
return new User(this);
}
}
}
优点:灵活控制入参,便于后续扩展。
这就是设计模式中的builder模式。
使用构建器
public class Main {
public static void main(String[] args) throws Exception {
User buyer = new User.Builder().buyerId(1L).build();
User fans = new User.Builder().fansType(1).fansId(1L).build();
}
}
适应变化
这个时候,如果产品提出支持匿名用户的需求,我们就可以从容应对了:
public class User {
private final long buyerId;
private final int fansType;
private final long fansId;
private final String nobody;
private User(Builder builder) {
buyerId = builder.buyerId;
fansType = builder.fansType;
fansId = builder.fansId;
nobody = builder.nobody;
}
public static class Builder {
private long buyerId;
private int fansType;
private long fansId;
private String nobody;
public Builder buyerId(long buyerId) {
this.buyerId = buyerId;
return this;
}
public Builder fansType(int fansType) {
this.fansType = fansType;
return this;
}
public Builder fansId(long fansId) {
this.fansId = fansId;
return this;
}
public Builder nobody(String nobody) {
this.nobody = nobody;
return this;
}
public User build() {
if (buyerId == 0 && fansType == 0 && fansId == 0 && nobody.equals("")) {
throw new RuntimeException("please init user data");
}
if (fansId != 0 && fansType == 0) {
throw new RuntimeException("invalid fans type");
}
if (fansType != 0 && fansId == 0) {
throw new RuntimeException("invalid fans id");
}
return new User(this);
}
}
}
参考资料
《effective java》