主题我们编码跟人生一样,需要有仪式感,优雅。哈哈 切入正题
先看一段代码
public ContactBusinessImpl(IContactDao contactDao, IIdMetaBusiness idMetaBusiness,
IDepartmentBusiness departmentBusiness,
IEuserBusiness euserBusiness,
IUserContactBusiness userContactBusiness,
IUserEnterpriseBusiness userEnterpriseBusiness,
IUserRoleBusiness userRoleBusiness,
IUserBusiness userBusiness,
ISensitiveWordBusiness sensitiveWordBusiness,
IProducerBusiness producerBusiness,
IOperationTracesBusiness operationTracesBusiness,
IMobileUserMappingDao mobileUserMappingDao,
ICommonBusiness commonBusiness) {
this.contactDao = contactDao;
this.idMetaBusiness = idMetaBusiness;
this.departmentBusiness = departmentBusiness;
this.euserBusiness = euserBusiness;
this.userContactBusiness = userContactBusiness;
this.userEnterpriseBusiness = userEnterpriseBusiness;
this.userRoleBusiness = userRoleBusiness;
this.userBusiness = userBusiness;
this.sensitiveWordBusiness = sensitiveWordBusiness;
this.producerBusiness = producerBusiness;
this.operationTracesBusiness = operationTracesBusiness;
this.mobileUserMappingDao = mobileUserMappingDao;
this.commonBusiness = commonBusiness;
}
这样的构造是不是让人蛋疼, 然后如果需要传入非必须属性的时候 怎么办? 构造方法参数太多了,很容易传错。
在此我么想到了 set 如下
public String getShoes() {
return shoes;
}
public void setShoes(String shoes) {
this.shoes = shoes;
}
......
这种缺点有很多,缺点1 如果我要定义 final 的成员呢?
然后比如这样 缺点2 set 几十个的时候:
Contact contact = new Contact();
contact.setContactId(rs.getString("contactId"));
contact.setEnterpriseId(rs.getString("enterpriseId"));
contact.setDepartmentId(rs.getString("departmentId"));
contact.setUserId(rs.getString("userId"));
contact.setEuserId(rs.getString("euserId"));
contact.setContactSort(rs.getInt("contactSort"));
contact.setContactLevel(rs.getInt("contactLevel"));
contact.setDetail(rs.getString("detail"));
contact.setCreateUserId(rs.getString("createUserId"));
非常的不优雅。
缺点 3 调用者可能拿到不完整状态的对象,这种方式是 先创建对象、后赋值,用户不知道什么时候拿到的对象是完整的,构建完成的。很有可能你只 set 了一两个属性就返回了,一些必要的属性没有被赋值。
回到主题: 优雅的 变种builder 模式
直接上代码:
public class ContactSingleExportBo{
private String departmentPath;
private String contactId;
private String name;
private String mobile;
private final String departmentId;
private String email;
private String position;
private String contactSort;
private String deptVisib;
private String euserType;
private String otherPhone;
private String userData;
private String tel;
private String contactLevel;
private String departmentSort;
private String departmentDepth;
public static ContactSingleExportBo.Builder builder(String departmentId) {
return new ContactSingleExportBo.Builder(departmentId);
}
// 构造 ,参数为它的静态内部类,使用静态内部类的变量一一赋值
private ContactSingleExportBo(Builder builder) {
departmentPath = builder.departmentPath;
contactId = builder.contactId;
name = builder.name;
mobile = builder.mobile;
departmentId = builder.departmentId;
email = builder.email;
position = builder.position;
contactSort = builder.contactSort;
deptVisib = builder.deptVisib;
euserType = builder.euserType;
otherPhone = builder.otherPhone;
userData = builder.userData;
tel = builder.tel;
contactLevel = builder.contactLevel;
departmentSort = builder.departmentSort;
departmentDepth = builder.departmentDepth;
}
//的静态内部类,成员变量和 本类 的一致
public static final class Builder {
private String departmentPath;
private String contactId;
private String name;
private String mobile;
private final String departmentId; //必选 初始化在构造器中
private String email;
private String position;
private String contactSort;
private String deptVisib;
private String euserType;
private String otherPhone;
private String userData;
private String tel;
private String contactLevel;
private String departmentSort;
private String departmentDepth;
public Builder(String departmentId) {
this.departmentId = departmentId;
}
public Builder departmentPath(String val) {
departmentPath = val;
return this;
}
public Builder contactId(String val) {
contactId = val;
return this;
}
public Builder name(String val) {
name = val;
return this;
}
public Builder mobile(String val) {
mobile = val;
return this;
}
public Builder email(String val) {
email = val;
return this;
}
public Builder position(String val) {
position = val;
return this;
}
public Builder contactSort(String val) {
contactSort = val;
return this;
}
public Builder deptVisib(String val) {
deptVisib = val;
return this;
}
public Builder euserType(String val) {
euserType = val;
return this;
}
public Builder otherPhone(String val) {
otherPhone = val;
return this;
}
public Builder userData(String val) {
userData = val;
return this;
}
public Builder tel(String val) {
tel = val;
return this;
}
public Builder contactLevel(String val) {
contactLevel = val;
return this;
}
public Builder departmentSort(String val) {
departmentSort = val;
return this;
}
public Builder departmentDepth(String val) {
departmentDepth = val;
return this;
}
public ContactSingleExportBo build() {
return new ContactSingleExportBo(this);
}
}
}
看起来代码很多, 其实都可以自动生成,
还有 IEDA 可以使用插件 直接注解 ,更优雅,
/**
* 删除文档元数据
*/
@Getter
@Setter
@Builder
public class DocNodeLocationMeta {
@NotNull(message = "文档类型不能为null")
private String indexType; // 索引类型
@NotNull(message = "分片信息不能为null")
private String indexShardingData; // 分片字段
@NotNull(message = "文档标识符不能为null")
private String docIdentifier; // 文档标识符
private String routingData; // 路由数据
}
是不是很简单了? 注解自行了解插件lombok
可以看到
然后我们来看看它的链式调用:
这里灰常优雅 ,先赋值,后创建对象,最终调用 build() 方法才创建了构建类的对象,保证了状态的完整性。
总结:
经典的 Builder 模式定义为:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。