需求如图
需要依据动作 来执行 状态的改变
最开始 写法:
public enum AuditActionEnum {
commit("commit", "提交审核"),
approvePass("approvePass", "审核通过"),
approveReject("approveReject", "审核拒绝");
private String key;
private String desc;
AuditActionEnum(String key, String desc) {
this.key = key;
this.desc = desc;
}
public String getKey() {
return this.key;
}
public String getDesc() {
return this.desc;
}
public static AuditActionEnum match(String key) {
for (AuditActionEnum e : AuditActionEnum.values()) {
if (e.getKey().equals(key)) {
return e;
}
}
return null;
}
}
通过状态:来做对应的数据库处理
if (AuditActionEnum.commit.getKey().equals(auditAction)) {
updateWrapper.set("audit_state", AuditStateEnum.committed.getKey());
updateWrapper.set("commit_time", auditCommitResDto.getCommitTime() == null ? DateUtil.getCurrentDatetime() : auditCommitResDto.getCommitTime());
}
if (AuditActionEnum.approvePass.getKey().equals(auditAction)) {
updateWrapper.set("is_master", EffectMasterEnum.master.getKey());
updateWrapper.set("is_effective", EffectMasterEnum.effect.getKey());
updateWrapper.set("audit_time", auditCommitResDto.getAuditTime() == null ? DateUtil.getCurrentDatetime() : auditCommitResDto.getAuditTime());
updateWrapper.set("audit_id", auditCommitResDto.getAuditId());
updateWrapper.set("audit_state", auditCommitResDto.getAuditState());
}
if (AuditActionEnum.approveReject.getKey().equals(auditAction)) {
updateWrapper.set("is_master", EffectMasterEnum.master.getKey());
updateWrapper.set("is_effective", EffectMasterEnum.un_effect.getKey());
updateWrapper.set("audit_time", auditCommitResDto.getAuditTime() == null ? DateUtil.getCurrentDatetime() : auditCommitResDto.getAuditTime());
updateWrapper.set("audit_state", auditCommitResDto.getAuditState());
updateWrapper.set("audit_id", auditCommitResDto.getAuditId());
}
写完之后觉得不妥 太多 if else
改为 使用策略模式:
策略接口:
@Component
public interface IAuditStrategy {
void doAction(IService service , Long id , AuditCommitResDto auditCommitResDto);
}
@Component("commit")
public class CommitAuditStrategy implements IAuditStrategy {
@Override
public void doAction(IService service, Long id, AuditCommitResDto auditCommitResDto) {
service.update(new UpdateWrapper<>()
.set("audit_id", auditCommitResDto.getAuditId())
.set("commit_time", auditCommitResDto.getCommitTime())
.set("audit_state", auditCommitResDto.getAuditState())
.eq("id", id)
);
}
}
具体实现子类:
@Component("approvePass")
public class ApprovePassAuditStrategy implements IAuditStrategy {
@Override
public void doAction(IService service, Long id, AuditCommitResDto auditCommitResDto) {
//审核通过先把之前数据失效 ,在把通过的这条生效
service.update(new UpdateWrapper<>()
.set("is_effective", EffectMasterEnum.effect.getKey())
.eq("master_id", id)
);
service.update(new UpdateWrapper<>()
.set("is_effective", EffectMasterEnum.effect.getKey())
.set("audit_time", auditCommitResDto.getAuditTime())
.set("audit_state", auditCommitResDto.getAuditState())
.eq("id", id)
);
}
}
通过 ioc 容器注入 并调用:
@Autowired
private Map<String, IAuditStrategy> auditStrategyMap;
调用代码:
auditStrategyMap.get(dto.getAuditAction()).doAction(this,id,auditCommitResDto);
======================================================================================= 经好友提示直接使用 String 作为策略的key容易与其他bean 冲突 所以使用 枚举类作为 key较好,这里引用
ApplicationContextAware
好处是不用重新 加载一遍 上下文 applicationContext (如直接用
ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext-common.xml");
AbcService abcService = (AbcService)appContext.getBean("abcService");
因为它会重新装载
applicationContext-common.xml
并实例化上下文bean,如果有些线程配置类也是在这个配置文件中,那么会造成做相同工作的的线程会被启两次。一次是web容器初始化时启动,另一次是上述代码显示的实例化了一次。当于重新初始化一遍!!!!这样就产生了冗余。
)
所以新增一个工厂类 去注册策略的生成
@Component
public class IAuditStrategyFactory implements ApplicationContextAware {
private Map<AuditActionEnum, IAuditStrategy> iAuditActionStateMap = new ConcurrentHashMap<>();
public IAuditStrategy getStrategy(AuditActionEnum auditActionEnum) {
return iAuditActionStateMap.get(auditActionEnum);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, IAuditStrategy> map = applicationContext.getBeansOfType(IAuditStrategy.class);
for(Map.Entry<String, IAuditStrategy> entry:map.entrySet()){
iAuditActionStateMap.put(AuditActionEnum.match(entry.getKey()), entry.getValue());
}
}
}