状态模式(STATE),别名状态对象(Objects for States),允许一个对象在其内部状态改变时改变它的行为,看起来就像修改了它的类,属于对象行为型模式。状态模式通过将所有与特定状态相关的行为封装到一个或多个状态对象中,当状态改变时,其行为也会随着改变,从而简化大量的条件判断,使代码逻辑更清晰,更易于维护。大千世界,可以看做各个状态的转换。人,生老病死;水,固液气三态转化;天气,阴晴不定。就是这些状态的变换构成了奇妙的世界。玩个游戏都还分低中高级呢,所以状态模式用途大大地。
一、使用场景
1、一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为。俗话说小孩的脸,六月的天,说变就变。他高兴的时候手舞足蹈,伤心的时候大哭大闹,小孩的行为随着心情而改变。
2、一个操作中含有大量的多分支条件语句,且这些分支依赖于该对象的状态。状态模式将这些条件分支封装到多个状态类中,这些类可以独立变化。
3、封装状态转换的规则。状态模式中,各状态之间的转换即可以由状态类自己把握,也可以由环境类控制,集中而不失灵活。
二、UML图
三、Java 实现
package study.patterns.state; public class StatePattern { public static void main(String[] args) { TCPConnection connection = new TCPConnection(); connection.activeOpen(); connection.close(); } } class TCPConnection{ private TCPState state; public TCPConnection(){ state = TCPClosed.instance; } public void activeOpen(){ state.activeOpen(this ); } public void passiveOpen(){ state.passiveOpen(this ); } public void close(){ state.close(this ); } public void acknowledge(){ state.acknowledge(this ); } public void send(){ state.send(this ); } public void changeState(TCPState state){ System.out.println(this .state+ " ===> " +state); this .state = state; } public void processOCtet(String stream){ System.out.println("传输流数据:" +stream); } } abstract class TCPState{ public void transmit(TCPConnection connection,String data){} public void activeOpen(TCPConnection connection){} public void passiveOpen(TCPConnection connection){} public void close(TCPConnection connection){} public void acknowledge(TCPConnection connection){} public void send(TCPConnection connection){} public void changeState(TCPConnection connection,TCPState state){ connection.changeState(state); } } class TCPEstablished extends TCPState{ public static TCPState instance = new TCPEstablished(); @Override public void transmit(TCPConnection connection, String data) { connection.processOCtet(data); } @Override public void close(TCPConnection connection) { System.out.println("Send FIN,receive ACK of FIN" ); changeState(connection, TCPClosed.instance); } public String toString(){ return "Established" ; } } class TCPClosed extends TCPState{ public static TCPState instance = new TCPClosed(); @Override public void activeOpen(TCPConnection connection) { System.out.println("Send SYN,receive SYN,ACK,etc." ); changeState(connection, TCPEstablished.instance); } @Override public void passiveOpen(TCPConnection connection) { changeState(connection, TCPListen.instance); } public String toString(){ return "Closed" ; } } class TCPListen extends TCPState{ public static TCPState instance = new TCPListen(); @Override public void send(TCPConnection connection) { changeState(connection, TCPEstablished.instance); } public String toString(){ return "Listen" ; } }
运行结果:
Send SYN,receive SYN,ACK,etc. Closed ===> Established Send FIN,receive ACK of FIN Established ===> Closed
四、模式优缺点
优点:
1、将于特定状态相关的行为局部化,并将不同状态的行为分割开来。状态模式将所有与某个特定状态相关的行为封装到一个状态对象中,这样通过添加新的子类可以很容易的增加新的状态和转换。
2、使状态转换显示化。状态模式中不同状态之间的转换是通过切换环境类中的变量来实现的,如TCPConnection类中的TCPState对象引用,而不是为多个变量赋值,这样确保状态转换的原子性,防止环境类Context内部状态不一致现象的发生。
3、State对象可以被共享。对于那些没有内部状态,只有行为的轻量级State对象,各Context对象可以共享一个State对象,从而减少对象的数量。
缺点:
1、由于每个状态对应一个对象,所以会导致系统中类和对象的个数增加。
2、状态模式的设计和实现比较复杂,增加系统的复杂度。