开始写设计模式系列,希望自己可以坚持下来.
第六篇:状态模式
什么是状态模式
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
很多人都会疑问状态模式和策略模式的区别在哪?实际上状态模式和策略模式很相似,甚至他们的UML图都是一致的,那么他们的区别在哪呢?我们再来回想下策略模式,
- 策略模式:创建一个策略的抽象,在这个接口声明算法函数,创建不同的策略实现类来实现算法,在Context类里,外部模块通过更换不同的策略实现从而达到不同的效果。策略模式的行为是相互独立的,可以相互替换的。
- 状态模式:状态模式的创建过程和策略模式一致,但是他的目的和意图却完全不同,状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。用户不应该来指定状态(除了初始状态),而是在满足一定条件下内部将其状态自动切换。
火车的状态模式:
在生活中火车经历的状态一般是从发车->加速->减速->加速…..->减速->停车,那么我们来实现它:
State状态接口:
package top.huyuxin.statemodel;
public interface State {
abstract void run(int speed);
}
发车状态:
package top.huyuxin.statemodel;
public class StartState implements State {
@Override
public void run(int speed) {
// 当前为发车状态,火车开始提速
System.out.println("火车开车正在提速!");
Context.Handle.getInstance().setState(new SpeedState());
}
}
加速状态:
package top.huyuxin.statemodel;
public class SpeedState implements State {
@Override
public void run(int speed) {
if(speed>=350){
System.out.println("到达时速上限,开始减速!");
Context.Handle.getInstance().setState(new SlowState());
}else{
System.out.println("火车当前时速:"+speed+",正在加速!");
Context.Handle.getInstance().speed+=50;
}
}
}
减速状态:
package top.huyuxin.statemodel;
public class SlowState implements State {
@Override
public void run(int speed) {
if(speed<250){
System.out.println("到达时速下限,开始减速!");
Context.Handle.getInstance().setState(new SpeedState());
}else{
System.out.println("火车当前时速:"+speed+",正在减速!");
Context.Handle.getInstance().speed-=50;
}
}
}
停车状态:
package top.huyuxin.statemodel;
public class StopState implements State{
@Override
public void run(int speed) {
System.out.println("火车准备停靠,开始减速,当前时速:"+speed);
Context.Handle.getInstance().speed-=50;
if(Context.Handle.getInstance().speed==0){
System.out.println("火车停止运行停靠成功!");
}
}
}
Context:
package top.huyuxin.statemodel;
public class Context {
public int speed=0;//时速
public int distance=0;//距离
private Context() {
super();
}
public static class Handle{
private static Context context=new Context();
public static Context getInstance() {
return context;
}
}
private State state;
/**
* protected 防止外部模块修改状态
* @param state
*/
protected void setState(State state) {
this.state = state;
}
public void run(){
if(state==null){
state=new StartState();
}
for(;;){
state.run(speed);
distance+=10;
//开始停靠
if(distance>300){
state=new StopState();
if(speed==-50){
break;
}
}
}
}
}
Main:
package top.huyuxin.statemodel.main;
import top.huyuxin.statemodel.Context;
import top.huyuxin.statemodel.Context.Handle;
public class Main {
public static void main(String[] args) {
Context.Handle.getInstance().run();
}
}
输出:
火车开车正在提速!
火车当前时速:0,正在加速!
火车当前时速:50,正在加速!
火车当前时速:100,正在加速!
火车当前时速:150,正在加速!
火车当前时速:200,正在加速!
火车当前时速:250,正在加速!
火车当前时速:300,正在加速!
到达时速上限,开始减速!
火车当前时速:350,正在减速!
火车当前时速:300,正在减速!
火车当前时速:250,正在减速!
到达时速下限,开始减速!
火车当前时速:200,正在加速!
火车当前时速:250,正在加速!
火车当前时速:300,正在加速!
到达时速上限,开始减速!
火车当前时速:350,正在减速!
火车当前时速:300,正在减速!
火车当前时速:250,正在减速!
到达时速下限,开始减速!
火车当前时速:200,正在加速!
火车当前时速:250,正在加速!
火车当前时速:300,正在加速!
到达时速上限,开始减速!
火车当前时速:350,正在减速!
火车当前时速:300,正在减速!
火车当前时速:250,正在减速!
到达时速下限,开始减速!
火车当前时速:200,正在加速!
火车当前时速:250,正在加速!
火车准备停靠,开始减速,当前时速:300
火车准备停靠,开始减速,当前时速:250
火车准备停靠,开始减速,当前时速:200
火车准备停靠,开始减速,当前时速:150
火车准备停靠,开始减速,当前时速:100
火车准备停靠,开始减速,当前时速:50
火车停止运行停靠成功!
其实经过这样简单的倒腾这已经是一个简易的有限状态机。当然按关于简易有限状态机的实现,网上还有一种利用enum(枚举)的实现方式,当状态比较简单还是可以使用的,但是状态过多时不建议使用,这会使得代码的可读性变得十分差。
扩展
在我们生活中还有很多的在这种情况,比如电梯在运行时他的状态应该是,开门->关门->升降->停止->开门->关门,在升降的过程中是不可能执行开门状态的,关门和开门进行时却可以自由切换,等等这些复杂的状态处理。我们可以通过建立链表关系,二叉树等数据结构的关系来实现。