一、定义
官方定义:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类,(State Pattern)是设计模式的一种,属于行为模式。
我的理解:当一个对象具有多种状态的时候,将这些状态抽取出来。每一种状态对应的是一种行为,执行相关的行为会导致状态的改变。比如订单的“未支付状态”,它执行“支付动作”后,订单的状态转变为了“已支付状态”。将这些状态抽取出来,独立成为类,好处是将状态的转变转移到了“状态类”中,避免了客户端调用环境中大量的if-else判断状态的语句。
推荐经典文章:Java设计模式——状态模式(STATE PATTERN)
二、优缺点
1.避免了过多的switch-case 或者 if-else语句。
2.符合开闭原则和单一职责原则。每个状态都是一个子类,要修改的话,只要修改某个子类。
缺点是
1.如果状态过多,会导致状态子类数量过多,系统复杂性变高。
三、经典代码 第一个例子
一种状态对应的是一种行为。
package test; //电梯 public class Lift { //开门状态常量 public static final OpeningState OPENING_STATE = new OpeningState(); //关门状态常量 public static final CloseState CLOSE_STATE = new CloseState(); //运行状态常量 public static final RunningState RUNNING_STATE = new RunningState(); //停止状态常量 public static final StoppingState STOPPING_STATE = new StoppingState(); //当前电梯的状态的引用 private LiftState liftState; public LiftState getLiftState() { return liftState; } //在设置当前状态的时候,要指明这个状态是哪个电梯的状态。 //当然,就是当前这个电梯对象 public void setLiftState(LiftState liftState) { /** * 电梯Lift 中 维护了当前的 电梯状态 * 具体的电梯状态要指明:当前的状态 ,你是“哪个电梯”的状态 * “哪个电梯”这里的话,就是当前的这个电梯对象 */ liftState.setLift(this); this.liftState = liftState; } //电梯的行为,它对应的是一种状态,比如开门状态,那么电梯就是在开门中 public void open(){ this.liftState.open(); } public void close(){ this.liftState.close(); } //电梯的行为,它对应的是一种状态,比如运行状态,那么电梯就是在运行中 public void run(){ this.liftState.run(); } public void stop(){ this.liftState.stop(); } public static void main(String[] args) { Lift lift = new Lift(); lift.setLiftState(CLOSE_STATE); lift.open(); lift.close(); lift.run(); lift.open(); } }
package test; //抽象电梯状态 public abstract class LiftState { protected Lift lift;//当前这个状态,它是哪个电梯的状态?因此维护了电梯的引用 public abstract void open(); public abstract void close(); public abstract void run(); public abstract void stop(); public Lift getLift() { return lift; } public void setLift(Lift lift) { this.lift = lift; } }
package test; //开门状态 public class OpeningState extends LiftState{ public void open() { System.out.println("正在开门"); } //关门的行为会导致电梯的状态转为关闭状态,关闭状态又对应的是 关闭的具体动作 public void close() { super.lift.setLiftState(Lift.CLOSE_STATE); super.lift.getLiftState().close(); } public void run() { // TODO Auto-generated method stub } public void stop() { // TODO Auto-generated method stub } }
package test; public class CloseState extends LiftState{ public void open() { super.lift.setLiftState(Lift.OPENING_STATE); super.lift.getLiftState().open(); } public void close() { System.out.println("正在关门"); } public void run() { super.lift.setLiftState(Lift.RUNNING_STATE); super.lift.getLiftState().run(); } public void stop() { // TODO Auto-generated method stub } }
package test; public class RunningState extends LiftState{ public void open() { // TODO Auto-generated method stub } public void close() { // TODO Auto-generated method stub } public void run() { System.out.println("正在运行"); } public void stop() { super.lift.setLiftState(Lift.STOPPING_STATE); super.lift.getLiftState().stop(); } }
package test; public class StoppingState extends LiftState{ public void open() { super.lift.setLiftState(Lift.OPENING_STATE); super.lift.getLiftState().open(); } public void close() { super.lift.setLiftState(Lift.CLOSE_STATE); super.lift.getLiftState().close(); } public void run() { super.lift.setLiftState(Lift.OPENING_STATE); super.lift.getLiftState().open(); } public void stop() { System.out.println("正在停止"); } }
四、与策略模式的区别
状态模式中的不同的状态,它们会在执行另外不同的状态对应的行为的时候,状态会有切换,因此各种状态之间存在联系。
策略模式是根据相关的条件进行判断,从而选择相关的策略,不同策略之间没有联系。
分割线--------------------------------------------------------------------------------------------
下一篇:中介者设计模式21