设计模式-策略模式实战
策略模式三个元素:
1:抽象策略接口(相当于每个if-else都会去执行的一个方法接口)
2:环境角色:是我们用来选择执行某个策略的操作类
3:具体策略类:相当于if-else 里的具体内容
采用策略模式原因:做工单类的业务,执行的操作过多,且对应不同的结果,导致接口实现出现大量if-else,或者swich方法,所以采用策略模式。-----其实是看着心烦。
首先是两个实体类,一个工单表的,一个流程表的,当操作改变,两张表都需要修改数据和新增。
/** 主键 */
private Long id;
/** 工单编号(自动生成) */
@Excel(name = "工单编号(自动生成)")
private String code;
/** 紧急程度(来自字典项) */
@Excel(name = "紧急程度")
private String urgency;
/** 报修人id(关联用户表sys_user) */
@Excel(name = "报修人id")
private Long repairUserId;
/** 报修人 */
@Excel(name = "报修人")
private String repairUserName;
/** 报修科室(关联科室表sys_dept) */
@Excel(name = "报修科室")
private Long deptId;
/** 保修电话 */
@Excel(name = "保修电话")
private String repairPhone;
/** 故障资产id */
@Excel(name = "故障资产id")
private Long assetsId;
/** 工单来源(来自字典项) */
@Excel(name = "工单来源(来自字典项)")
private String repairSource;
/** 影响范围(来自字典项) */
@Excel(name = "影响范围(来自字典项)")
private String reach;
/** 故障分类(关联故障分类表tbl_fault_type) */
@Excel(name = "故障分类")
private Long faultTypeId;
/** 状态(0:服务台解决 1:其他) */
@Excel(name = "状态(0:服务台解决 1:其他)")
private String status;
/** 故障标题 */
@Excel(name = "故障标题")
private String faultTitle;
/** 故障描述 */
@Excel(name = "故障描述")
private String description;
/** 故障原因 */
@Excel(name = "故障原因")
private String faultReason;
/** 事件原因 */
@Excel(name = "事件原因")
private String eventReason;
/** 处理过程 */
@Excel(name = "处理过程")
private String solveProcess;
/** 通话记录*/
@Excel(name = "通话记录")
private Long callId;
/** 报修时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "报修时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date repairTime;
/** 要求完成时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "要求完成时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date finishTime;
/** 流程节点 */
@Excel(name = "流程节点")
private String processNode;
/** 删除标志 */
private String delFlag;
/** 处理人id(关联用户表sys_user) */
@Excel(name = "处理人id")
private Long handlerUserId;
/** 处理人姓名 */
@Excel(name = "处理人姓名")
private String handlerUserName;
/** 建单人id(关联用户表sys_user) */
@Excel(name = "建单人id")
private Long createUserId;
/** 催单次数 */
private int count;
/** 附件id */
private String attachmentIds;
/** 是否服务台解决 */
private String isPhone;
private Long groupId;
流程:
/** $column.columnComment */
private Long id;
/** 工单id */
@Excel(name = "工单id")
private Long workId;
/** 流程节点 */
@Excel(name = "流程节点")
private String processNode;
/** 发起人姓名 */
@Excel(name = "发起人姓名")
private String sponsorName;
/** 发起人id */
@Excel(name = "发起人id")
private Long sponsorId;
/** 处理人姓名 */
@Excel(name = "处理人姓名")
private String handlerName;
/** 处理人id */
@Excel(name = "处理人id")
private Long handlerId;
/** 处理时长 */
@Excel(name = "处理时长")
private String handlerTime;
/** 转交原因 */
@Excel(name = "转交原因")
private String description;
/** 删除标志(0代表存在 2代表删除) */
private String delFlag;
业务实现:
/**
* 修改节点流程(采用策略模式,根据节点的不同选择不同的策略模式)
* @author lity
* @Date 2020-07-28
* @param req
* @return
*/
@Override
public boolean updateProcessNode(WorkProcessReq req) {
String processType = req.getProcessType();
//环境角色
WorkProcessContext workProcessContext = null;
boolean result = false;
//选择策略
workProcessContext = new WorkProcessContext(SpringUtils.getBean(WORK_PROCESS_NAME+processType));
//执行策略
result = workProcessContext.executeStrategy(processType,req);
return result;
}
首先创建一个接口,这个接口就是策略模式的接口,就是在执行策略时所有策略类都要执行的方法。
抽象策略类(Strategy):策略的抽象,选择工单流程节点(接单,派单,退回等))的抽象。
此接口放到dao层mapper里即可。
public interface ProcessStrategy {
/**
* @Author lity
* @Description //通过策略模式修改工单状态增加流程节点
* @Date 2020/7/31
* @Param [processType]
* @return boolean
**/
boolean updateProcessNode(String processType, WorkProcessReq req);
}
这是所有的具体的策略类,每一个类执行一种方法,相当于if-else 里的内容
这是其中一个类要用到@Component这个注解并命名,否则在service 实现的时候这个类不会注入到spring,里面所引入的mapper也就变成了null。
/**
*@ClassName Again
*@Description 重派
*@Author lity
*@Date 2020/7/31 10:21
*@Version 1.0
*/
@Component(WorkServiceImpl.WORK_PROCESS_NAME + "1")
public class AgainDistributionWork implements ProcessStrategy {
@Resource
private SysUserMapper sysUserMapper;
@Resource
private ProcessMapper processMapper;
@Resource
private WorkMapper workMapper;
/**
* @Author lity
* @Description //重派工单
* @Date 2020/7/31
* @Param [processType, req]
* @return boolean
**/
@Override
public boolean updateProcessNode(String processType, WorkProcessReq req) {
Process process = new Process();
Work work = new Work();
//因为每个流程节点的发起人都是当前登录用户,所以直接存储
//发起人id(当前登录用户)
Long sponsorId = SecurityUtils.getLoginUser().getUser().getUserId();
String sponsorName = sysUserMapper.selectUserById(sponsorId).getNickName();
//发起人姓名
if (null != req.getWorkId()) {
//工单id
process.setWorkId(req.getWorkId());
work.setId(req.getWorkId());
}
process.setSponsorId(sponsorId);
process.setSponsorName(sponsorName);
process.setProcessNode(processType);
process.setHandlerId(req.getHandlerId());
String receiverName = sysUserMapper.selectUserById(req.getHandlerId()).getNickName();
process.setHandlerName(receiverName);
process.setCreateTime(DateUtils.getNowDate());
work.setProcessNode(processType);
work.setStatus(WorkStatusConstants.WORK_DISTRIBUTION);
work.setUpdateTime(DateUtils.getNowDate());
int processResult = processMapper.insertProcess(process);
int workResult = workMapper.updateWork(work);
if (processResult > 0 && workResult > 0) {
return true;
}else {
return false;
}
}
}
这是Context 环境角色
/**
*@ClassName WorkProcessContext
*@Description 策略模式环境
*@Author lity
*@Date 2020/7/31 11:12
*@Version 1.0
*/
public class WorkProcessContext {
/**
* 环境角色持有对策略角色的一个应用,这里主要是用到了多态
*/
private ProcessStrategy processStrategy;
/**
*设置执行置策略
**/
public WorkProcessContext(ProcessStrategy processStrategy){
this.processStrategy = processStrategy;
}
/**
*执行策略
**/
public boolean executeStrategy(String processType, WorkProcessReq req){
return processStrategy.updateProcessNode(processType, req);
}
}
2020-08-03