本文最后更新于:3 years ago
在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于 行为型模式
在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。
如果想了解状态模式的具体的介绍,菜鸟教程介绍得比较详细↓菜鸟教程-状态模式
结构图
优缺点 优点:
1、封装了转换规则。 2、枚举可能的状态,在枚举状态之前需要确定状态种类。 3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。 4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。 5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点:
1、状态模式的使用必然会增加系统类和对象的个数。 2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。 3、状态模式对”开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。
使用场景 1、行为随状态改变而改变的场景。 2、条件、分支语句的代替者。
实现代码 首先提出需求,我们模拟将汽车在不同状态时,所能执行的操作也是不一样的 什么意思呢?当汽车在驾驶状态时,我们是不能够开车门和关车门的,但是可以进行驾驶和停下操作 而当汽车在关闭状态下,我们是可以开车门,关车门,但是不能够执行驾驶和停下的操作
需求很简单,正常实现,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 class Main { public static void main (String[] args) { Car car = new Car(); CarState state = new CarState(); state.state = "Running" ; car.setState(state); car.runTheCar(); car.stopTheCar(); car.openTheDoor(); car.closeTheDoor(); } }class Car { CarState carState; public void setState (CarState state) { this .carState = state; } public void openTheDoor () { if (carState.state.equals("Running" )) { System.out.println("Car is Running!Can't open the door" ); } if (carState.equals("Closed" )) { System.out.println("Car is Closed!Can open the door" ); } } public void closeTheDoor () { if (carState.state.equals("Running" )) { System.out.println("Car is Running!Can't close the door" ); } if (carState.state.equals("Closed" )){ System.out.println("Car is Closed!Can close the door" ); } } public void runTheCar () { if (carState.state.equals("Running" )) { System.out.println("Car is Running!Can run the door" ); } if (carState.state.equals("Closed" )) { System.out.println("Car is Closed!Can't run the car" ); } } public void stopTheCar () { if (carState.state.equals("Running" )) { System.out.println("Car is Running!Can stop the door" ); } if (carState.state.equals("Closed" )) { System.out.println("Car is Closed!Can't stop the car" ); } } }class CarState { String state; }
结果如下:
Car is Running!Can run the door Car is Running!Can stop the door Car is Running!Can't open the door Car is Running!Can't close the door
我们在Car中对每个方法进行了比较,如果是驾驶状态/停下状态,不同的操作有着不同的结果 代码很简单,但是细想一下,此时当我们添加新的状态时,是不是很不方遍,你需要在每一个方法中都需要去添加相应的反应, 这个时候就需要用到状态模式了
当一个类中的动作根据它的状态的不同会有不同的反应,这个时候就可以应用State模式 如果一个类它的很多operation,都是需要根据不同的State来实现,那么我们就可以把State抽象出来,在State中实现这些方法
还是刚刚那个需求,我们用State模式,重构一下代码
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 public class Main { public static void main (String[] args) { Car car = new Car(); CarState carCloseState = new CarClosedState(); car.setState(carCloseState); car.closeTheDoor(); car.runTheCar(); car.openTheDoor(); car.stopTheCar(); } }public class Car { private CarState state; public Car () { this .state = null ; } public void setState (CarState state) { this .state = state; } public void openTheDoor () { state.openTheDoor(); } public void closeTheDoor () { state.closeTheDoor(); } public void runTheCar () { state.runTheCar(); } public void stopTheCar () { state.stopTheCar(); } }public abstract class CarState { abstract void openTheDoor () ; abstract void closeTheDoor () ; abstract void runTheCar () ; abstract void stopTheCar () ; }public class CarOpenState extends CarState { @Override void openTheDoor () { System.out.println("Car is Open!Can open the door" ); } @Override void closeTheDoor () { System.out.println("Car is Open!Can close the door" ); } @Override void runTheCar () { System.out.println("Car is Open!Can run thr car" ); } @Override void stopTheCar () { System.out.println("Car is Open!Can't stop the door" ); } }public class CarClosedState extends CarState { @Override void openTheDoor () { System.out.println("Car is Closed!Can open the door" ); } @Override void closeTheDoor () { System.out.println("Car is Closed!Can close the door" ); } @Override void runTheCar () { System.out.println("Car is Closed!Can't run the car" ); } @Override void stopTheCar () { System.out.println("Car is Closed!Can't stop the car" ); } }public class CarRunningState extends CarState { @Override void openTheDoor () { System.out.println("Car is Running!Can't open the door" ); } @Override void closeTheDoor () { System.out.println("Car is Running!Can't close the door" ); } @Override void runTheCar () { System.out.println("Car is Running!Can run the door" ); } @Override void stopTheCar () { System.out.println("Car is Running!Can stop the door" ); } }public class CarStoppedState extends CarState { @Override void openTheDoor () { System.out.println("Car is Stop!Can open the door" ); } @Override void closeTheDoor () { System.out.println("Car is Stop!Can close the door" ); } @Override void runTheCar () { System.out.println("Car is Stop!Can run the door" ); } @Override void stopTheCar () { System.out.println("Car is Stop!Can stop the door" ); } }
结果如下:
Car is Closed!Can close the door Car is Closed!Can't run the car Car is Closed!Can open the door Car is Closed!Can't stop the car
你可以试着先自己去理解这段代码
我们先创建一个接口CarState,其中的有四个方法,我们将模拟不同状态下的不同操作开门、关门、开车、停车 接着,我们模拟了汽车的四种状态:CarOpenState、CarClosedState、CarRunnning、CarStopping,并且都继承CarState,重写方法 最后我们创建Car,在Car中我们创建CarState来表示Car的状态 在Main中我们将创建的具体状态传入实例化的car,调用相应的方法,栗子还是很容易理解的
对于State模式来讲,如果你想要扩展自己(CarState)的方法,就不建议采用State模式了(当你扩展operation时,State模式中所有operation都需要扩展) 如果并不需要对State的类型进行扩展,也不建议采用State模式(会导致子类很多) 当你的operation不会进行扩展时,可以采用State模式
在学习State模式的时候,有看到一篇写的很好的关于State模式的文章这里可以去看看,写的很用心,不像我水一水文章👇
设计模式:状态(State)模式