状态模式
状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。当控制一个对象状态转换的条件表达式过于复杂时的情况,把条件判断转移到表示不同状态的一系列类中,把复杂的判断逻辑简化。
结构图:
业务中若条件判断很多,例如:
public class Test { public static void main(String[] args) { int hour = 14; if(hour>=0 && hour<6){ System.out.println("目前是凌晨状态"); } else if(hour<=12){ System.out.println("目前是上午状态"); }else if(hour<=18){ System.out.println("目前是下午状态"); }else if(hour<=24){ System.out.println("目前是夜晚状态"); }else{ System.out.println("时间越界!"); } } }
如果具体业务中每个条件判断内是非常复杂的逻辑,这段代码就会特别长,会产生代码坏味道(Long Method)。此时可以采用状态模式解决。
例:
public interface State { void handle(Context context); }
public class ConcreteState1 implements State { @Override public void handle(Context context) { if(context.getHour()>=0 && context.getHour()<=6){ // 0~6点是凌晨状态 System.out.println("目前是凌晨状态"); } else{ // 否则进入上午状态 context.setState(new ConcreteState2()); context.request(); } } }
public class ConcreteState2 implements State { @Override public void handle(Context context) { if(context.getHour()<=12){ // 6~12点前是上午状态 System.out.println("目前是上午状态"); } else{ // 否则进入下午状态 context.setState(new ConcreteState3()); context.request(); } } }
public class ConcreteState3 implements State { @Override public void handle(Context context) { if(context.getHour()<=18){ // 12~18点前是下午状态 System.out.println("目前是下午状态"); } // 否则进入夜晚状态 else{ context.setState(new ConcreteState4()); context.request(); } } }
public class ConcreteState4 implements State { @Override public void handle(Context context) { if(context.getHour()<=24){ // 18~24点前是夜晚状态 System.out.println("目前是夜晚状态"); } else{ System.out.println("时间越界!"); } } }
public class Context { private State state; private int hour; public State getState() { return state; } public void setState(State state) { this.state = state; } public int getHour() { return hour; } public void setHour(int hour) { this.hour = hour; } public void request(){ state.handle(this); } }
public class Test { public static void main(String[] args) { Context context = new Context(); context.setState(new ConcreteState1()); // 初始状态为状态1 context.setHour(14); context.request(); } }
输出:
目前是上午状态