状态模式:当对象状态改变时行为也随之改变,看起来就像是这个类发生了改变。
首先对象有状态,行为由状态决定。
假设现在有一个游戏角色,有正常状态、加速状态、减速状态、眩晕状态。
游戏角色不同状态下的行为是不同的,减速跑的慢一些、眩晕不能跑。
我们将游戏角色转换为代码,先看不使用状态模式的情况。
游戏角色类
public class Hero { public static final int COMMON = 1;//正常状态 public static final int SPEED_UP = 2;//加速状态 public static final int SPEED_DOWN = 3;//减速状态 public static final int SWIM = 4;//眩晕状态 private int state = COMMON;//默认是正常状态 public int getState() { return state; } public void setState(int state) { this.state = state; } public void run() { if(state == COMMON) { System.out.println("正常状态"); }else if(state == SPEED_UP) { System.out.println("加速状态"); } else if(state == SPEED_DOWN) { System.out.println("减速状态"); } else if(state == SWIM) { System.out.println("眩晕状态"); } } }
Main
public class Main { public static void main(String[] args) { //默认正常状态 Hero hcf = new Hero(); hcf.run(); //加速状态 hcf.setState(Hero.SPEED_UP); hcf.run(); //眩晕状态 hcf.setState(Hero.SWIM); hcf.run(); //减速状态 hcf.setState(Hero.SPEED_DOWN); hcf.run(); } }
运行结果:
正常状态
加速状态
眩晕状态
减速状态
游戏角色中有状态,执行run方法时会根据状态打印出不用的结果,即对象状态的改变也会造成行为的改变。
这样实现也可以,但如果后续分支状态过多,需要大量的if else,而且Hero的状态只对象Hero有效,怪兽同样有这些状态,
这些状态无法复用。
这时我们就可以采用状态模式
首先需要将状态抽取出来,每一个状态对应一个状态类
状态接口
public interface State { public void change(Hero hero); }
加速状态
public class SpeedUpState implements State { @Override public void change(Hero hero) {//传递英雄对象,改变英雄对象的状态 // TODO Auto-generated method stub hero.setState(this); } @Override public String toString() { return "加速状态"; } }
减速状态
public class SpeedDownState implements State { @Override public void change(Hero hero) {//传递英雄对象,改变英雄对象的状态 // TODO Auto-generated method stub hero.setState(this); } @Override public String toString() { return "减速状态"; } }
眩晕状态
public class SwimState implements State{ @Override public void change(Hero hero) {//传递英雄对象,改变英雄对象的状态 // TODO Auto-generated method stub hero.setState(this); } @Override public String toString() { return "眩晕状态"; } }
正常状态
public class CommonState implements State{ @Override public void change(Hero hero) {//传递英雄对象,改变英雄对象的状态 // TODO Auto-generated method stub hero.setState(this); } @Override public String toString() { return "正常状态"; } }
每一个状态对应一个状态类,当英雄状态需要发送变化时,只需创建状态类,然后将heroz作为参数,调用状态类的change方法。
change方法会将当前状态对象设置到hero中的state属性,后续直接获取英雄状态即可。
Main
public class Main { public static void main(String[] args) { Hero hcf = new Hero(); //正常状态 CommonState commonState = new CommonState(); commonState.change(hcf); System.out.println(hcf.getState().toString()); //加速状态 SpeedUpState speedUpState = new SpeedUpState(); speedUpState.change(hcf); System.out.println(hcf.getState().toString()); //眩晕状态 SwimState swimState = new SwimState(); swimState.change(hcf); System.out.println(hcf.getState().toString()); //减速状态 SpeedDownState speedDownState = new SpeedDownState(); speedDownState.change(hcf); System.out.println(hcf.getState().toString()); } }
运行结果:
正常状态
加速状态
眩晕状态
减速状态
后续还有新的状态只需添加状态类即可,而且可以进一步抽象,使Heor类和怪兽类实现同一个接口,这样这些状态对于Hero和怪兽都适用。
参考资料: