设计模式-状态模式
状态模式(State Pattern)
状态模式(State Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式描述了对象状态的变化以及对象如何在每一种状态下表现出不同的行为,避免了使用if-else或者switch-case语句,同时代码结构清晰能够保证扩展性和维护性。
但是状态模式违法开闭原则,而且在context类中耦合状态对象,当状态多的情况下,却会导致代码混乱而且不易维护。
状态模式与策略模式
状态模式:对象创建后,可以告诉客户从什么状态开始,然后随着时间推移改变自己的状态,而任何状态的改变都是定义好的。
策略模式:允许对象通过组合和委托来拥有不同的算法或行为。能实例化一个类,给它一个实现某些行为的策略对象,也可以在运行时改变行为。
状态模式结构:
环境角色(Context):也称上下文,定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。
抽象状态角色(State):定义一个接口,用以封装环境对象的一个特定的状态所对应的行为。
具体状态角色(ConcreteState):每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。
代码:
//State:定义一个接口,用以封装环境对象的一个特定的状态所对应的行为。 public interface State{ public void start(); public void running(); public void stop(); } //ConcreteState:每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。 public class StartState implements State{ private Machine machine; public StartState(Machine machine) {this.machine = machine;} @Override public void start() { System.out.println("准备中"); machine.setState(machine.getRunningState()); } @Override public void running() {System.out.println("不支持该操作");} @Override public void stop() {System.out.println("不支持该操作");} } //ConcreteState:每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。 public class RunningState implements State{ private Machine machine; public RunningState(Machine machine) {this.machine = machine;} @Override public void start() {System.out.println("不支持该操作");} @Override public void running() { System.out.println("执行中"); machine.setState(machine.getStopState()); } @Override public void stop() {System.out.println("不支持该操作");} } //ConcreteState:每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。 public class StopState implements State{ private Machine machine; public StopState(Machine machine) {this.machine = machine;} @Override public void start() {System.out.println("不支持该操作");} @Override public void running() {System.out.println("不支持该操作");} @Override public void stop() { System.out.println("暂停"); machine.setState(machine.getStartState()); } }
//Context:也称上下文,定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。 public class Machine{ private StartState startState; private RunningState runningState; private StopState stopState; //当前状态 private State state; //初始化 public Machine(){ this.startState = new StartState(this); this.runningState = new RunningState(this); this.stopState = new StopState(this); this.state = startState; } public StartState getStartState() {return startState;} public RunningState getRunningState() {return runningState;} public StopState getStopState() {return stopState;} //修改状态 public void setState(State state){this.state = state;} //调用状态方法 public void start(){state.start();} public void run(){state.running();} public void stop(){state.stop();} }
//方法调用 public class Client{ public static void main(String[] args) { Machine machine = new Machine(); machine.start(); machine.run(); machine.stop(); } }
优点:
1、代码结构化,易于维护、扩展。
2、每个状态只需要关心自己内部的实现,而不会影响到其他的,耦合降低。
缺点:
1、有多少的状态就得有多少的类,因此会创建大量的类。
2、代码结构变得复杂,不再是单个类中写满逻辑。
应用场景:
1、一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
2、操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。 通常,有多个操作包含这一相同的条件结构。
State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。