设计模式(二十)—状态模式

最后更新于:2022-04-01 16:26:36

**定义**:当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。 ## 一般模式 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340d0a479.jpg) state:抽象状态角色 ---|接口或抽象类,负责对象状态定义,并且封装环境角色以实现状态切换。 ConcreteState:具体状态角色 ---|每一个具体状态必须完成两个职责,本状态的行为管理以及去想状态处理,通俗的说,就是本状态下要做的事情, 以及本状态如何过渡到其他状态。 Context环境角色 ---|定义客户端需要的接口,并且负责具体状态的切换。 状态类是通过context(环境角色)来实现装之间的转换的。 ~~~ public class StateTest { public static void main(String[] args) { //提供一个环境角色 Context context = new Context(); //想让执行状态1的handle1方法 context.setCurrentState(new ConcreteState1()); //执行handle2方法 context.handle2(); } } /** * 抽象状态角色: * 封装环境角色,实现状态的切换 * @author Administrator */ abstract class State{ //提供一个环境角色,共子类访问 protected Context context; public void setContext(Context context) { this.context = context; } //抽像的行为1角色 public abstract void handle1(); //抽像的行为2角色 public abstract void handle2(); } /** * 负责具体状态的切换 * @author Administrator * */ class Context{ //里面封装了所有的状态方法 protected final static ConcreteState1 state1 = new ConcreteState1(); protected final static ConcreteState2 state2 = new ConcreteState2(); //设置当前状态 private State currentState; public State getCurrentState() { return currentState; } public void setCurrentState(State currentState) { this.currentState = currentState; //设置环境角色 this.currentState.setContext(this); } //提供handle1方法 public void handle1(){ this.currentState.handle1(); } //提供handle2方法 public void handle2(){ this.currentState.handle2(); } } /** * 具体状态类的实现类, * 主要抽象方法的具体实现方式。 * @author Administrator */ class ConcreteState1 extends State{ @Override public void handle1() { System.out.println("我是实现类1,的具体实现方法1..."); } @Override public void handle2() { System.out.println("我是实现类1,的具体实现方法2..."); //切换到ConcreteState2类的handle2方法,这里就相当于是状态的切换 super.context.setCurrentState(Context.state2); super.context.handle2(); } } /** * 具体状态类的实现类, * 主要抽象方法的具体实现方式。 * @author Administrator */ class ConcreteState2 extends State{ @Override public void handle1() { System.out.println("我是实现类2,的具体实现方法1..."); super.context.setCurrentState(Context.state1); super.context.handle1(); } @Override public void handle2() { System.out.println("我是实现类2,的具体实现方法2..."); } } ~~~ ## 一个例子:  一个电梯他有4中状态,打开,运行,停止,关闭。他们之间存在着紧密的状态切换关系。例如:  人乘坐电梯,打开-->关闭--->运行--->停止。关闭电梯时,可能存在运行和停止。我们通过程序  来模拟这里的状态之间的转换。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340d20824.jpg) ~~~ public class StateT { public static void main(String[] args) { //提供一个环境角色 LiftContext context = new LiftContext(); //设置环境角色,为打开状态 context.setCurrentLift(new Closeing()); context.close(); context.run(); context.stop(); } } /** * 抽象的装填类角色 * 定义抽像的方法,封装角色。 * @author Administrator */ abstract class ILift{ //定义一个环境角色,共子类调用 protected LiftContext context; public LiftContext getContext(){ return this.context; } public void setContext(LiftContext context) { this.context = context; } //电梯的打开状态 public abstract void open(); //电梯的打开关闭 public abstract void close(); //电梯的打开运行 public abstract void run(); //电梯的打开停止 public abstract void stop(); } /** * 抽象状态类的实现类 * @author Administrator */ class Openning extends ILift{ @Override public void open() { System.out.println("---电梯打开,请上去...或下去"); } @Override public void close() { //状态转换 super.context.setCurrentLift(LiftContext.CLOSE); //委托给关闭状态的类来执行 super.context.close(); } @Override public void run() { System.out.println("打开状态--不能运行.."); } @Override public void stop() { System.out.println("打开状态--已经停止"); } } /** * 抽象状态类的实现类 * @author Administrator */ class Closeing extends ILift{ @Override public void open() { //切换为打开状态 super.context.setCurrentLift(LiftContext.OPEN); super.getContext().open(); } @Override public void close() { System.out.println("电梯门关闭.."); } @Override public void run() { super.context.setCurrentLift(LiftContext.RUN); super.getContext().run(); } @Override public void stop() { } } /** * 抽象状态类的实现类 * @author Administrator */ class Running extends ILift{ @Override public void open() { System.out.println("运行中--电梯不能打开.."); } @Override public void close() { System.out.println("运行中--电梯已关闭.."); } @Override public void run() { System.out.println("---电梯正在运行..."); } @Override public void stop() { //运行状态--->停止状态 super.context.setCurrentLift(LiftContext.STOP); super.getContext().stop(); } } /** * 抽象状态类的实现类 * @author Administrator */ class Stoping extends ILift{ @Override public void open() { //停止之后-->打开电梯门 super.context.setCurrentLift(LiftContext.OPEN); super.getContext().open(); } @Override public void close() { System.out.println("停止状态--电梯还是关闭的.."); } @Override public void run() { System.out.println("停止状态--电梯没有运行.."); } @Override public void stop() { System.out.println("--电梯停止了.."); } } /** * 环境角色, * 用于转换他们之间的状态 * @author Administrator */ class LiftContext{ //封装四种状态类 protected static final Openning OPEN = new Openning(); protected static final Closeing CLOSE = new Closeing(); protected static final Running RUN = new Running(); protected static final Stoping STOP = new Stoping(); //提供一个状态类 private ILift currentLift; public ILift getCurrentLift() { return currentLift; } public void setCurrentLift(ILift currentLift) { this.currentLift = currentLift; //设置环境角色 this.currentLift.setContext(this); } //提供四种状态类的方法 public void open() { this.currentLift.open(); } //提供四种状态类的方法 public void close() { this.currentLift.close(); } //提供四种状态类的方法 public void run() { this.currentLift.run(); } //提供四种状态类的方法 public void stop() { this.currentLift.stop(); } } ~~~ **状态模式的优点:** ---|结构清晰 ---|遵循设计原则 ---|封装性非常好 **状态模式的缺点:** ---|环境角色中封装的角色子类太多。 不好管理。 **状态模式的使用场景** ---|行为随状态改变而改变的场景 ---|条件、分支判断语句的替代者。
';