状态模式的定义如下:
Allow an object to alter its behavior when its internal state changes. The objects will appear to change
its class.
当一个对象内在状态改变时允许其改变行为这个对象看起来像改变了其类。
状态模式的核心是封装,状态的变更引起了行为的变更,从外部看起来就好像这个对象对应的类放生了改变一样。
状态模式角色:
1.State——抽象状态角色:接口或抽象类,负责对象状态定义,并且封装环境角色已实现状态切换
2.ConcreteState——具体状态角色:每一个具体状态必需完成两个职责:本状态的行为管理以及趋向状态处理,通俗的说,
就是本状态下要做的事情,以及本状态如何过度到其他状态。
3.Context——环境角色:定义客户端需要的接口,并且负责具体状态的切换
//抽象状态角色 public abstract class State{ protected Context context; //设置环境角色 public void setContext(Context _context){ this.context=_context; } //行为1 public abstract void handle1(); //行为2 public abstract void handle2(); } //具体状态角色 public class ConcreteState1 extends State{ @Override public abstract void handle1(){ } @Override public abstract void handle2(){ //设置当前的状态为状态2 super.context.setCurrentState(Context.STATE2); //过渡到state2状态,有Context实现 super.context.handle2(); } } public class ConcreteState2 extends State{ @Override public abstract void handle1(){ //设置当前的状态为状态1 super.context.setCurrentState(Context.STATE1); //过渡到state2状态,有Context实现 super.context.handle1(); } @Override public abstract void handle2(){ } } //具体环境角色 /* 环境角色有两个不成文的约束: 1.把状态对象声明为静态常量,有几个状态对象就声明几个静态常量 2.环境角色具有状态抽象角色定义的所有行为,具体执行使用委托方式 */ public class Context{ //定义状态 public final static State STATE1=new ConcreteState1(); public final static State STATE2=new ConcreteState2(); //当前状态 private State CurrentState; //获取当前的状态 public State getCurrentState(){ return CurrentState; } //设置当前状态 public void setCurrentState(State currentState){ this.CurrentState=currentState; //切换状态 this.CurrentState.setContext(this); } //行为委托 public abstract void handle1(){ this.CurrentState.handle1(); } public abstract void handle2(){ this.CurrentState.handle2(); } } //场景类 public class Client{ public static void main(String[] args){ //定义环境角色 Context context=new Context(); //初始化状态 context.setCurrentState(new ConcreteState1()); //行为执行 context.handle1(); } }
状态模式的优点:
1.结构清晰:避免了过多的switch...case或者if...else语句的使用,避免了程序的复杂性,提高系统的可维护性。
2.遵循设计原则:体现了开闭原则和单一职责原则,每个状态都是一个子类,要增加一个状态就要增加子类,要修改状态
只修改一个子类就可以了。
3.封装性非常好:状态变化放置到类的内部来实现,外部的调用不用知道类内部如何实现状态和行为的变换
缺点:状态子类太多会导致类膨胀
状态模式的使用场景:
1.行为随状态改变而改变的场景
2.条件,分支判断语句的替代者
注意事项:
状态模式适用于当某个对象在它的状态发生改变时,它的行为也随着发生变化,也就是说在行为受状态约束的情况下可以使用
状态模式,而且使用时对象的状态最好不要超过5个