一、是什么?
定义: 当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。
在这个模式中,一个类的行为是根据状态改变而改变的。比如下午做什么是根据心情状态改变的,心情好出去玩,心情不好就宅家,同样是做什么,心情状态不同,干的事情就不一样。
而且它可以内部的切换状态,比如心情不好下午宅家,宅到一半彩票中了五万,心情状态变好了,然后就出去Happy了。这也是和策略模式的不同之一,策略模式的行为一旦确定就不能改变了。
下面就以工单流转的例子细说。
二、类图
三、代码实现
FlowTask
:流程环节的抽象接口。相当于是状态的行为抽象。
Start
、Task1
、End
:具体的流程环节实现,状态对应的具体行为。
WorkFlow
:状态的环境,用于执行状态对应的行为。
// 流程环节抽象
public interface FlowTask {
void next(WorkFlow workFlow);
void back(WorkFlow workFlow);
}
// 开始环节
public class Start implements FlowTask{
@Override
public void next(WorkFlow workFlow) {
System.out.println("保存开始环节的信息....");
workFlow.changeFlowTask(new Task1());
}
@Override
public void back(WorkFlow workFlow) {
System.out.println("已经是第一步了....");
}
}
// 环节1
public class Task1 implements FlowTask{
@Override
public void next(WorkFlow workFlow) {
System.out.println("保存Task1环节的信息....");
workFlow.changeFlowTask(new End());
}
@Override
public void back(WorkFlow workFlow) {
System.out.println("重置开始环节的信息....");
workFlow.changeFlowTask(new Start());
}
}
// 结单环节
public class End implements FlowTask{
@Override
public void next(WorkFlow workFlow) {
System.out.println("结单....");
}
@Override
public void back(WorkFlow workFlow) {
System.out.println("重置结单环节的信息....");
workFlow.changeFlowTask(new Task1());
}
}
// 工单
public class WorkFlow {
private FlowTask task;
public WorkFlow(FlowTask task) {
this.task = task;
}
public void changeFlowTask(FlowTask task) {
System.out.println(this.task.getClass().getName() + "结束,当前环节:" + task.getClass().getName());
this.task = task;
}
public void next() {
System.out.println("下一步");
this.task.next(this);
}
public void back() {
System.out.println("驳回");
this.task.back(this);
}
// 运行
public static void main(String[] args) {
WorkFlow workFlow = new WorkFlow(new Start());
workFlow.next();
workFlow.back();
workFlow.next();
workFlow.next();
workFlow.next();
}
}
运行结果:
我们可以发现除了初始化时赋值了具体流程,在之后的工单流转中,不再由客户端指定流程环节,而是状态内部的自动转换,状态不同,工单next行为也不同。
代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中
四、优缺点
优点:
- 方便维护
- 很强的可读性
- 符合“开闭原则”。容易增删状态
缺点:
- 使用不当会产生大量类,加大维护难度。但这是小缺点,它是真香。
五、与策略模式的区别
我认为最大区别就是状态切换,在状态模式中状态是可以在运行期间变化的,行为也会变化。在策略模式中,策略一旦确定,就不能改变,比如线程池的拒绝策略,创建线程池时指定拒绝策略,在运行的期间就不能再改变。
还有就是关注的点不一样,状态模式关注的是状态,而且每个状态的行为目的不一样。而策略模式关注的是行为,行为目的是一样,比如拒绝策略,不同的拒绝策略的行为本质都是拒绝线程任务。