策略枚举的用法一:状态流转
说明
本文只对策略枚举可以使用的场景进行说明,不做其他介绍。提供额外的实现思路。
状态流转
在开发过程中,难免会遇到状态之间的流转,如何方便维护并且能够一目了然的知道状态之间的流转呢?
例如:
上图可以看出,我们有状态组:黄色框的内容;操作组:连接线上的内容。
就可以使用一个状态枚举来包装
package com.strategy.enums;
/**
* 单据状态
*/
public enum StatusEnum {
/** 已提报 */
HAD_CREATE(1, "已新建"),
/** 已提报 */
HAD_SUBMIT(2, "已提报") ,
/** 已审核" */
HAD_AUDIT(3, "已审核") ,
/** 已退回 */
HAD_BACK(4, "已退回"),
/** 已拒绝 */
HAD_REJECT(5, "已拒绝"),
/** 已生成结算 */
HAD_USE(6, "已生成结算"),
/** 已关闭 */
HAD_CLOSE(7, "已关闭");
/** 枚举值 */
private int index;
/** 枚举描述 */
private String name;
StatusEnum(int index, String name) {
this.index = index;
this.name = name;
}
public int getIndex() {
return index;
}
public String getName() {
return name;
}
}
如何改造成策略枚举呢,加上操作(方法)与绑定(重写)。
package com.strategy.enums;
/**
* 单据状态
*/
public enum StatusEnum {
/** 已提报 */
HAD_CREATE(1, "已新建") {
@Override
public StatusEnum create() {
return HAD_CREATE;
}
@Override
public StatusEnum save() {
return HAD_CREATE;
}
@Override
public StatusEnum submit() {
return HAD_SUBMIT;
}
@Override
public StatusEnum close() {
return HAD_CLOSE;
}
},
/** 已提报 */
HAD_SUBMIT(2, "已提报") {
@Override
public StatusEnum pass() {
return HAD_AUDIT;
}
@Override
public StatusEnum back() {
return HAD_BACK;
}
@Override
public StatusEnum reject() {
return HAD_REJECT;
}
},
/** 已审核" */
HAD_AUDIT(3, "已审核") {
@Override
public StatusEnum used() {
return HAD_USE;
}
},
/** 已退回 */
HAD_BACK(4, "已退回") {
@Override
public StatusEnum save() {
return HAD_BACK;
}
@Override
public StatusEnum submit() {
return HAD_SUBMIT;
}
@Override
public StatusEnum close() {
return HAD_CLOSE;
}
},
/** 已拒绝 */
HAD_REJECT(5, "已拒绝") {
},
/** 已使用 */
HAD_USE(6, "已使用") {
},
/** 已关闭 */
HAD_CLOSE(7, "已关闭") {
};
/** 枚举值 */
private int index;
/** 枚举描述 */
private String name;
/** 创建 */
public StatusEnum create() {
throw new RuntimeException("当前状态【" + this.getName() + "】不允许执行【创建】操作");
}
/** 暂存 */
public StatusEnum save() {
throw new RuntimeException("当前状态【" + this.getName() + "】不允许执行【暂存】操作");
}
/** 提报 */
public StatusEnum submit() {
throw new RuntimeException("当前状态【" + this.getName() + "】不允许执行【提报】操作");
}
/** 通过 */
public StatusEnum pass() {
throw new RuntimeException("当前状态【" + this.getName() + "】不允许执行【通过】操作");
}
/** 驳回 */
public StatusEnum back() {
throw new RuntimeException("当前状态【" + this.getName() + "】不允许执行【驳回】操作");
}
/** 拒绝 */
public StatusEnum reject() {
throw new RuntimeException("当前状态【" + this.getName() + "】不允许执行【拒绝】操作");
}
/** 使用 */
public StatusEnum used() {
throw new RuntimeException("当前状态【" + this.getName() + "】不允许执行【使用】操作");
}
/** 关闭 */
public StatusEnum close() {
throw new RuntimeException("当前状态【" + this.getName() + "】不允许执行【关闭】操作");
}
/** 使用的重点方法 */
public static StatusEnum valueOf(Integer index) {
if (index == null) {
return null;
}
for (StatusEnum modeEnum : StatusEnum.values()) {
if (index == modeEnum.getIndex()) {
return modeEnum;
}
}
return null;
}
StatusEnum(int index, String name) {
this.index = index;
this.name = name;
}
public int getIndex() {
return index;
}
public String getName() {
return name;
}
}
以上,就实现了策略枚举,一个类实现了流程图的完整状态流转。 流程图已经准备好了,那要如何使用呢?很简单,只要一句话即可。 当我们修改数据状态的时候,首先需要从库中获取该数据的原始状态,已经知道我们当前的请求操作【按钮、方法】是什么。所以两个决定因数已经有了,就可以进行操作
package com.strategy.enums;
import java.util.ArrayList;
import java.util.List;
/**
* 单据状态 测试类
*/
public class StatusEnumMainTest {
public static void main(String[] args) {
new StatusEnumMainTest().test();
}
private void test() {
// 假设从数据库中获取了改数据的状态
List<StatusEnumTest> list = getInitList();
// 已新建数据进行提报(成功)
StatusEnumTest statusEnumTest1 = getStatusEnumTest(1L, list);
System.out.println("修改前的数据:" + statusEnumTest1.toString());
statusEnumTest1.setStatus(StatusEnum.valueOf(statusEnumTest1.getStatus()).submit().getIndex());
System.out.println("修改后的数据:" + statusEnumTest1.toString());
// 已关闭数据进行修改(失败)
StatusEnumTest statusEnumTest7 = getStatusEnumTest(7L, list);
System.out.println("关闭前的数据:" + statusEnumTest7.toString());
statusEnumTest1.setStatus(StatusEnum.valueOf(statusEnumTest7.getStatus()).save().getIndex());
System.out.println("关闭后的数据:" + statusEnumTest7.toString());
}
private StatusEnumTest getStatusEnumTest(Long id, List<StatusEnumTest> list) {
for (StatusEnumTest data : list) {
if (id.equals(data.getId())) {
return data;
}
}
return null;
}
private List<StatusEnumTest> getInitList() {
List<StatusEnumTest> list = new ArrayList<StatusEnumTest>();
list.add(new StatusEnumTest(1L, 1, "这是已新建数据"));
list.add(new StatusEnumTest(2L, 2, "这是已提报数据"));
list.add(new StatusEnumTest(3L, 3, "这是已审核数据"));
list.add(new StatusEnumTest(4L, 4, "这是已退回数据"));
list.add(new StatusEnumTest(5L, 5, "这是已拒绝数据"));
list.add(new StatusEnumTest(6L, 6, "这是已使用数据"));
list.add(new StatusEnumTest(7L, 7, "这是已关闭数据"));
return list;
}
private class StatusEnumTest {
private Long id;
private Integer status;
private String other;
public StatusEnumTest(Long id, Integer status, String other) {
this.id = id;
this.status = status;
this.other = other;
}
public Long getId() {
return id;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getOther() {
return other;
}
@Override
public String toString() {
return "StatusEnumTest{" + "id=" + id + ", status=" + status + ", other='" + other + '\'' + '}';
}
}
}
运行结果如下
修改前的数据:StatusEnumTest{id=1, status=1, statusName=已新建, other='这是已新建数据'}
修改后的数据:StatusEnumTest{id=1, status=2, statusName=已提报, other='这是已新建数据'}
关闭前的数据:StatusEnumTest{id=7, status=7, statusName=已关闭, other='这是已关闭数据'}
java.lang.RuntimeException: 当前状态【已关闭】不允许执行【暂存】操作
at com.strategy.enums.StatusEnum.save(StatusEnum.java:100)
at com.strategy.enums.StatusEnumMainTest.test(StatusEnumMainTest.java:26)
at com.strategy.enums.StatusEnumMainTest.main(StatusEnumMainTest.java:12)
这样我们就能够使用代码来控制状态的流转。既能控制流程,也能获取下一个状态,一举两得。
转载自:https://juejin.cn/post/7052649692936536078