建造者模式实际上是常用的设计模式。
顾名思义,builder的意思是建造者或者建筑工人,谈到建造自然会想到楼房。楼房是千差万别的,楼房的外形、层数、内部房间的数量、房间的装饰等等都不一样,
但是对于建造者来说,抽象出来的建筑流程是确定的,往往建筑一座楼房包括下面的步骤:
(1)打桩,建立基础
(2)建立框架等。建造者模式的本质和建造楼房是一致的:即流程不变,但每个流程实现的具体细节则是经常变化的。
建造者模式的好处就是保证了流程不会变化,流程即不会增加、也不会遗漏或者产生流程次序错误,这是非常重要的。
我们熟知的楼歪歪事件,官方的解释就是由于先建立楼房后,再建设停车场造成的,这是典型的建造次序错乱
先看个类的源代码
/**
* 发起流程审核时 初始化审核日志对象信息
* @param id
* @param opinion
* @param nodeName
* @return
*/
public static CheckLog initStartApplyCheckLog(String id, String opinion,String nodeName) {
CheckLog checkLog=new CheckLog();
User currentUser= PlatformServiceInvoke.getCurrentUser();
checkLog.setContractId(id);
//若是一天中来回几次审核,那么数据顺序将异常,因此将记录审核时间的精确度提高
checkLog.setHandleDate(DateTimeUtils.format(new Date(), DateTimeUtils.DATE_TIME_FORMAT));
checkLog.setPersonId(currentUser.getId());
checkLog.setNodeNum(1);
checkLog.setNodeState("firstNode");
checkLog.setPerNodeName("startNode");
checkLog.setCurNodeName(nodeName);
checkLog.setPsersonName(currentUser.getUserName());
checkLog.setOpinion(opinion);
return checkLog;
}
/**
* 流程结束时 初始化结束的审核日志信息
* @param id
* @param curNode
* @return
*/
public static CheckLog initEndCheckLog(String id, String curNode) {
CheckLog checkLog=new CheckLog();
User currentUser= PlatformServiceInvoke.getCurrentUser();
checkLog.setContractId(id);
//若是一天中来回几次审核,那么数据顺序将异常,因此将记录审核时间的精确度提高
checkLog.setHandleDate(DateTimeUtils.format(new Date(), DateTimeUtils.DATE_TIME_FORMAT));
checkLog.setPersonId(currentUser.getId());
checkLog.setPsersonName(currentUser.getUserName());
checkLog.setCurNodeName("结束审核");
checkLog.setPerNodeName(curNode);
return checkLog;
}
/**
* 流程普通提交时 初始化审核日志对象
* @param id
* @param opinion
* @param nodeName
* @param perNode
* @param nodeId
* @return
*/
public static CheckLog initCheckLog(String id, String opinion,String nodeName,String perNode,String nodeId) {
CheckLog checkLog=new CheckLog();
User currentUser= PlatformServiceInvoke.getCurrentUser();
checkLog.setContractId(id);
// checkLog.setHandleDate(DateTimeUtils.format(new Date(), DateTimeUtils.DATE_FORMAT));
//若是一天中来回几次审核,那么数据顺序将异常,因此将记录审核时间的精确度提高
checkLog.setHandleDate(DateTimeUtils.format(new Date(), DateTimeUtils.DATE_TIME_FORMAT));
checkLog.setPersonId(currentUser.getId());
checkLog.setPsersonName(currentUser.getUserName());
checkLog.setOpinion(opinion);
checkLog.setCurNodeName(nodeName);
checkLog.setCurNodeId(nodeId);
checkLog.setPerNodeName(perNode);
return checkLog;
}
/**
* 流程回退时 初始化审核日志信息
* @param id
* @param perLog
* @param checkLog
*/
public static void initBackCheckLog(String id, CheckLog perLog, CheckLog checkLog) {
checkLog.setOperationExplain(RecordEnum.SUBMIT_TO_BACK.getValue());
checkLog.setCurNodeId(CommonEnum.EMPTY.getValue());
checkLog.setCurNodeName(CommonEnum.EMPTY.getValue());
checkLog.setPerNodeName(perLog.getCurNodeName());
}
流程在驱动过程中会把流程流转的相关信息记录下来,这个类是初始化审核日志对象时的一个类。
重构过程中就试着改成建造者模式来优化,由于该对象的初始化还不够复杂,可能体现的价值还不太明细。
CheckLogBuilder 抽象建造者代码
public abstract class CheckLogBuilder {
public static String FIRST_NODE="firstNode";
public static String START_NODE="startNode";
//初始化审核日志对象
public abstract void initCheckLog(String relId, String opinion,String curNodeName,String preNodeName,String curNodeId);
//获取审核日志对象
public abstract CheckLog getCheckLog();
}
ComNodeCheckLogBuilder 建造者
public class ComNodeCheckLogBuilder extends CheckLogBuilder{
CheckLog checkLog=new CheckLog();
@Override
public void initCheckLog(String contractId, String opinion,String curNodeName,String perNodeName,String curNodeId) {
User currentUser= PlatformServiceInvoke.getCurrentUser();
checkLog.setContractId(contractId);
//若是一天中来回几次审核,那么数据顺序将异常,因此将记录审核时间的精确度提高
checkLog.setHandleDate(DateTimeUtils.format(new Date(), DateTimeUtils.DATE_TIME_FORMAT));
checkLog.setPersonId(currentUser.getId());
checkLog.setPsersonName(currentUser.getUserName());
checkLog.setOpinion(opinion);
checkLog.setCurNodeName(curNodeName);
checkLog.setCurNodeId(curNodeId);
checkLog.setPerNodeName(perNodeName);
}
@Override
public CheckLog getCheckLog() {
return checkLog;
}
}
EndNodeCheckLogBuilder 建造者
public class EndNodeCheckLogBuilder extends CheckLogBuilder{
CheckLog checkLog=new CheckLog();
@Override
public void initCheckLog(String contractId, String opinion,String nodeName,String perNode,String curNodeId) {
User currentUser= PlatformServiceInvoke.getCurrentUser();
checkLog.setContractId(contractId);
//若是一天中来回几次审核,那么数据顺序将异常,因此将记录审核时间的精确度提高
checkLog.setHandleDate(DateTimeUtils.format(new Date(), DateTimeUtils.DATE_TIME_FORMAT));
checkLog.setPersonId(currentUser.getId());
checkLog.setPsersonName(currentUser.getUserName());
checkLog.setCurNodeName("结束审核");
checkLog.setPerNodeName(nodeName);
}
@Override
public CheckLog getCheckLog() {
return checkLog;
}
}
StartNodeCheckLogBuilder 建造者
public class StartNodeCheckLogBuilder extends CheckLogBuilder{
private CheckLog checkLog = new CheckLog();
@Override
public void initCheckLog(String relId, String opinion,String curNodeName,String preNodeName,String curNodeId) {
User currentUser= PlatformServiceInvoke.getCurrentUser();
checkLog.setContractId(relId);
//若是一天中来回几次审核,那么数据顺序将异常,因此将记录审核时间的精确度提高
checkLog.setHandleDate(DateTimeUtils.format(new Date(), DateTimeUtils.DATE_TIME_FORMAT));
checkLog.setPersonId(currentUser.getId());
checkLog.setNodeNum(1);
checkLog.setNodeState(FIRST_NODE);
checkLog.setPerNodeName(START_NODE);
checkLog.setCurNodeName(curNodeName);
checkLog.setPsersonName(currentUser.getUserName());
checkLog.setOpinion(opinion);
}
@Override
public CheckLog getCheckLog() {
return checkLog;
}
}
BackNodeCheckLogBuilder 建造者
public class BackNodeCheckLogBuilder extends CheckLogBuilder {
CheckLog checkLog=new CheckLog();
@Override
public void initCheckLog(String contractId, String opinion,String nodeName,String perNode,String curNodeId) {
checkLog.setOperationExplain(RecordEnum.SUBMIT_TO_BACK.getValue());
checkLog.setCurNodeId(CommonEnum.EMPTY.getValue());
checkLog.setCurNodeName(CommonEnum.EMPTY.getValue());
checkLog.setPerNodeName(nodeName);
}
@Override
public CheckLog getCheckLog() {
return checkLog;
}
}
CheckLogDirector 导演类,当然我这还需要获取排序号,所以还有其他相关代码。
public class CheckLogDirector {
private CheckLogService checkLogService;
private CheckLogDirector(){
}
public CheckLogDirector(CheckLogService _checkLogService){
this.checkLogService=_checkLogService;
}
private CheckLogBuilder comNodeCheckLogBuilder = new ComNodeCheckLogBuilder();
/**
* 获取普通提交的审核日志对象
* @param relId
* @param opinion
* @param curNodeName
* @param preNodeName
* @param curNodeId
* @return
*/
public CheckLog getCheckLog(String relId, String opinion,String curNodeName,String preNodeName,String curNodeId){
comNodeCheckLogBuilder.initCheckLog(relId,opinion,curNodeName,preNodeName,curNodeId);
CheckLog checkLog=comNodeCheckLogBuilder.getCheckLog();
checkLog.setNodeNum(checkLogService.getLogNum(relId));
return checkLog;
}
private CheckLogBuilder endNodeCheckLogBuilder = new EndNodeCheckLogBuilder();
/**
* 获取结束结点的审核对象
* @param relId
* @param opinion
* @param preNodeName
* @return
*/
public CheckLog getEndCheckLog(String relId, String opinion, String preNodeName) {
endNodeCheckLogBuilder.initCheckLog(relId,opinion,"",preNodeName,"");
CheckLog checkLog=endNodeCheckLogBuilder.getCheckLog();
checkLog.setNodeNum(checkLogService.getLogNum(relId));
return checkLog;
}
}
这种改造自然导致增加了好几个类,但对于审核对象的维护确实要明确许多,