背景
最近在做数据安全管控,涉及一个模块包含了很多状态(待发布、发布中、发布成功、发布失败、撤销、删除),看到这么多状态感觉头皮发麻啊,就想着有没有一种模式去解决这种问题,自然就找到了状态模式。
状态模式
程序在任意时刻仅可处于几种有限的状态中。 在任何一个特定状态中, 程序的行为都不相同, 且可瞬间从一个状态切换到另一个状态。 不过, 根据当前状态, 程序可能会切换到另外一种状态, 也可能会保持当前状态不变。 这些数量有限且预先定义的状态切换规则被称为转移。
很明显我遇到的这个问题就很适合用状态模式去解决:
- 1、状态有限,待发布、发布中、发布成功、发布失败、撤销、删除。
- 2、存在状态的瞬间切换。比如:发布中 -> 发布成功;发布中 -> 发布失败。
具体实现
上下文
原始对象被称为上下文 (context), 它并不会自行实现所有行为, 而是会保存一个指向表示当前状态的状态对象的引用, 且将所有与状态相关的工作委派给该对象。
我个人的理解上下文就像是一个管理者,他负责管理状态,切换不同的状态去执行不同的业务。
public class PolicyContext {
private PolicyState policyState;
public Boolean updatePolicyStatus(String status, ExtraData extraData) {
policyState.doAction(this, extraData);
return Boolean.TRUE;
}
}
状态
如需将上下文转换为另外一种状态, 则需将当前活动的状态对象替换为另外一个代表新状态的对象。 采用这种方式是有前提的: 所有状态类都必须遵循同样的接口, 而且上下文必须仅通过接口与这些对象进行交互。
状态很简单,其实像是一个抽象类,他是每一种状态都必须继承或者实现的类,这样上下文才可以对状态进行切换。
public interface PolicyState {
/**
* 具体业务实现方法
* @param policyContext 策略上下文
* @return
*/
Boolean doAction(PolicyContext policyContext, ExtraData extraData);
}
状态具体实现
我举出的只是一个发布中的状态例子,其他的状态也和此类似。看伪代码可以发现,处于发布中状态的策略,其实还可能切换到发布成功或者发布失败状态。
但是,我并没有在此类中去具体实现发布成功或者发布失败的业务,个人觉得这也是状态策略的魅力所在点之一(模块式开发管理),不同的状态处理不同的业务,不存在业务交叉,这样以后无论你是增加一个状态还是删除一个状态,都不会对代码有很大的改动。
public class PolicyReleasingState implements PolicyState {
@Autowired private PolicyService policyService;
@Override
public Boolean doAction(PolicyContext policyContext, ExtraData extraData) {
System.out.println("策略发布中。。。。。。");
// 1、 首先核验策略状态,只有处于待发布状态,才可以发布
Policy policyInfo = policyService.getPolicyInfo(extraData.getPolicyId());
String status = policyInfo.getStatus();
if (StringUtils.equals(status, "待发布")) {
// 2、 修改策略状态为发布中
policyContext.setPolicyState(this);
Boolean releaseSuccess = policyService.updatePolicyStatus("发布中");
// 3、 发布成功,修改策略状态为成功,发布失败,修改策略状态为失败
if (releaseSuccess) {
policyContext.setPolicyState(new PolicyReleaseSuccessState());
policyContext.updatePolicyStatus("发布成功", extraData);
} else {
policyContext.setPolicyState(new PolicyReleaseFailState());
policyContext.updatePolicyStatus("发布失败", extraData);
}
} else {
log.info("非法操作");
}
return Boolean.TRUE;
}
}
状态模式 VS 策略模式
状态模式可能看上去与策略模式相似,但有一个关键性的不同——在状态模式中, 特定状态知道其他所有状态的存在, 且能触发从一个状态到另一个状态的转换; 策略则几乎完全不知道其他策略的存在。
个人理解状态具有属性性质,属性性质代表着可预见性,也就是我肯定知道我有多少个状态;而策略则不一样,策略不具备属性性质,他是一个单独的个体,每一个单独的个体都不知道其他的个体的作用(存在)。
举个例子,现在短信平台可以选择腾讯或者阿里,但是腾讯或者阿里不是短信的属性。假如项目中使用了这两个作为短信发送的渠道,就可以使用策略模式去管理。
One comment
继续加油啊