Design Patterns(二十) State
The state pattern is a behavioral software design pattern that allows an object to alter its behavior when its internal state changes. This pattern is close to the concept of finite-state machines. The state pattern can be interpreted as a strategy pattern, which is able to switch a strategy through invocations of methods defined in the pattern’s interface.
前言 状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式。状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化,对于客户端而言,无须关心对象状态的转换以及对象所处的当前状态,无论对于何种状态的对象,客户端都可以一致处理。
状态模式 基本介绍:
1) 状态模式(State Pattern):它主要用来解决对象在多种状态转换时,需要对外输出不同的行为的问题。状态和行为是一一对应的,状态之间可以相互转换; 2) 当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类。
角色介绍:
1) Context 类为环境角色, 用于维护State实例,这个实例定义当前状态; 2) State 是抽象状态角色,定义一个接口封装与Context 的一个特点接口相关行为; 3) ConcreteState 具体的状态角色,每个子类实现一个与Context 的一个状态相关行为。
状态模式-UML图:
状态模式-实例图:
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 public class StateDemo { public static void main (String[] args) { FlowContext context = new FlowContext(); context.setMessage("本人老王,因为十一家里有事情,所以要多请三天假,希望公司能够审核通过" ); context.start(context); } } abstract class State { public abstract void Handle (Context context) ; } class ConcreteStateA extends State { @Override public void Handle (Context context) { context.setState(new ConcreteStateB()); } } class ConcreteStateB extends State { @Override public void Handle (Context context) { context.setState(new ConcreteStateA()); } } class Context { State state; public Context (State state) { super (); this .state = state; } public State getState () { return state; } public void setState (State state) { this .state = state; System.out.println("当前状态为" + state); } public void request () { state.Handle(this ); } } abstract class Node { private static String name; public abstract void nodeHandle (FlowContext context) ; public String getName () { return name; } public void setName (String name) { this .name = name; } } class LeadNode extends Node { @Override public void nodeHandle (FlowContext context) { if (!context.isFlag()) { System.out.println(context.getMessage()); if (context != null && 3 == context.getStatus()) { setName("张经理" ); context.setMessage(context.getMessage() + getName() + "审核通过;" ); context.setStatus(0 ); context.setNode(new HrNode()); context.getNode().nodeHandle(context); } } else { System.err.println("流程已经结束" ); } } } class HrNode extends Node { @Override public void nodeHandle (FlowContext context) { if (!context.isFlag()) { if (context != null && 0 == context.getStatus()) { setName("HR李" ); System.out.println(context.getMessage() + getName() + "审核通过" ); context.setStatus(0 ); context.setFlag(true ); } } else { System.out.println("流程已经结束" ); } } } class FlowContext { private boolean flag; private int status; private String message; private Node node; public boolean isFlag () { return flag; } public void setFlag (boolean flag) { this .flag = flag; } public int getStatus () { return status; } public void setStatus (int status) { this .status = status; } public String getMessage () { return message; } public void setMessage (String message) { this .message = message; } public Node getNode () { return node; } public void setNode (Node node) { this .node = node; } public static boolean start (FlowContext context) { Node node = new LeadNode(); context.setNode(node); context.setStatus(3 ); context.getNode().nodeHandle(context); if ("HR李" .equals(node.getName()) && 0 == context.getStatus() && context.isFlag()) { System.out.println("审核通过,流程结束" ); return true ; } else { System.out.println("审核未通过,流程已经结束" ); return false ; } } public FlowContext () { super (); } }
总结 状态模式的注意事项和细节:
1) 代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中; 2) 方便维护。将容易产生问题的if-else语句删除了,如果把每个状态的行为都放到一个类中,每次调用方法时都要判断当前是什么状态,不但会产出很多if-else语句,而且容易出错; 3) 符合“开闭原则”。容易增删状态; 4) 会产生很多类。每个状态都要一个对应的类,当状态过多时会产生很多类,加大维护难度; 5) 应用场景:当一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状态要求有不同的行为的时候,可以考虑使用状态模式。
延伸 设计模式之状态模式 状态模式总结-java版 状态模式-菜鸟教程 Design Patterns - State Pattern 尚硅谷Java设计模式,韩顺平图解java设计模式
<
Design Patterns(二十一) Strategy
Design Patterns(十九) Interpreter
>