1.概述
本文将介绍在Java中如何通过枚举来实现状态机。通过与接口及具体类来的实现方式来说明枚举实现状态机器的优势。
2.Java Enums
枚举是一种定义了一组常量的特殊的类。通过枚举使代码可读性更好。我们以人力资源系统为例,该系统可以批准雇员离职申请。这个申请需要小组领导审批,随后将审批结果提交给部门领导。部门领导最终有权利批准申请。
首先定义离职请求涉及的状态。
public enum LeaveRequestState {
Submitted,
Escalated,
Approved
}
使用枚举:
LeaveRequestState state = LeaveRequestState.Submitted;
枚举可以包含方法,我们可以在枚举中写一个抽象方法,每个枚举实例都必须实现这个方法。由于Java 枚举会隐式继承java.lang.Enum类,因此不能在继承其它类。然而,可以再实现接口。
public enum LeaveRequestState {
Submitted {
@Override
public String responsiblePerson() {
return "Employee";
}
},
Escalated {
@Override
public String responsiblePerson() {
return "Team Leader";
}
},
Approved {
@Override
public String responsiblePerson() {
return "Department Manager";
}
};
public abstract String responsiblePerson();
}
我们通过定义responsiblePerson来获取处理每个状态的负责人。比如Escalated状态是由Team Leader来处理。
LeaveRequestState state = LeaveRequestState.Escalated;
assertEquals("Team Leader", state.responsiblePerson());
同理可以检查Approved状态负责人
LeaveRequestState state = LeaveRequestState.Approved;
assertEquals("Department Manager", state.responsiblePerson());
3.枚举实现状态机
通过枚举实现状态机时,我们不要显式去设置状态。我们只需要提供状态转移的逻辑。
public enum LeaveRequestState {
Submitted {
@Override
public LeaveRequestState nextState() {
return Escalated;
}
@Override
public String responsiblePerson() {
return "Employee";
}
},
Escalated {
@Override
public LeaveRequestState nextState() {
return Approved;
}
@Override
public String responsiblePerson() {
return "Team Leader";
}
},
Approved {
@Override
public LeaveRequestState nextState() {
return this;
}
@Override
public String responsiblePerson() {
return "Department Manager";
}
};
public abstract LeaveRequestState nextState();
public abstract String responsiblePerson();
}
上面的例子中,状态机的转换通过枚举的方法nextState来实现。此外还可以根据希求提供previousState方法,来获得前一个状态。下面的测试来检查我们的实现
LeaveRequestState state = LeaveRequestState.Submitted;
state = state.nextState();
assertEquals(LeaveRequestState.Escalated, state);
state = state.nextState();
assertEquals(LeaveRequestState.Approved, state);
state = state.nextState();
assertEquals(LeaveRequestState.Approved, state);
我们从初始状态Submitted开始,并通过nextState方法来转换到下一个状态,直到Approved终止。
4.通过Java枚举实现状态机的优点
如果通过类来实现会产生大量的代码。而Java枚举是一组常量,我们可以通过使用枚举来定义状态。而枚举也可以包含行为,我们可以使用方法来实现状态机的转换。所有逻辑均放在枚举中使得代码简介干净,对于逻辑简单的状态机便于维护。