Java设计模式之从[游戏中的兵种状态变换]分析状态(State)模式
Java设计模式之从[游戏中的兵种状态转换]分析状态(State)模式
SwordState、BowState、ShieldState为此兵种的三个状态。KnightContext中有个SoldierState类型的成员state表示这个兵种的当前状态。请注意,我们并不希望把如何切换的过程写在KnightContext中(一般的想法可能是,在changeState中加入switch块,这样会使得KnightContext过于繁重),而是把如何转换写在了SoldierState的transform方法中。这样就避免了在KnightContext中加入大量的切换状态的代码。如果需要新增加一个状态,只需要修改和增加SoldierState的子类即可。对于每一个状态,它都有一个单独的子类来表示,因此在状态多的情况下会出现很多个子类,这也是状态模式的缺点。
假设我们正在做一个即时战略游戏,我们设计一个兵种,他在刚刚生产出来的时候是步兵,但是他可以切换武器,第一次切换会变成弓箭手,第二次切换会变成举着盾牌的装甲兵,第三次切换则又变成了步兵……如何实现这个切换的机制?我们一开始会想到,在步兵这个类中加入switch语句,然而这样的话,代码不利于扩展,不利于修改,这时我们就可以使用状态模式了。
状态模式允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
在本例中,这个兵种有3个状态——步兵、弓箭手和装甲兵。我们将这3个状态都继承于同一个基类SoldierState,我们还需要定义一个兵种类来包含一个SoldierState对象,以便它是用来存储这些状态的,在本例中这个类的名字叫做KnightContext。先看Java代码吧:
abstract class SoldierState { public abstract void show(); protected void changeState(KnightContext knight, SoldierState soldierState){ knight.changeState(soldierState); } public abstract void transform(KnightContext knight); } class KnightContext { SoldierState state; public KnightContext(){ state = SwordState.getState(); } public void changeState(SoldierState state){ this.state = state; state.show(); } public void transform(){ state.transform(this); } } class SwordState extends SoldierState{ private static SoldierState state = new SwordState(); public static SoldierState getState(){ return state; } public void show() { System.out.println("现在是步兵模式。"); } public void transform(KnightContext knight) { changeState(knight, BowState.getState()); } } class BowState extends SoldierState{ private static SoldierState state = new BowState(); public static SoldierState getState(){ return state; } public void show() { System.out.println("现在是弓箭模式。"); } public void transform(KnightContext knight) { changeState(knight, ShieldState.getState()); } } class ShieldState extends SoldierState{ private static SoldierState state = new ShieldState(); public static SoldierState getState(){ return state; } public void show() { System.out.println("现在是盾牌模式。"); } public void transform(KnightContext knight) { changeState(knight, SwordState.getState()); } } public class State { public static void main(String[] args) { KnightContext knight = new KnightContext(); knight.transform(); knight.transform(); knight.transform(); knight.transform(); knight.transform(); }
SwordState、BowState、ShieldState为此兵种的三个状态。KnightContext中有个SoldierState类型的成员state表示这个兵种的当前状态。请注意,我们并不希望把如何切换的过程写在KnightContext中(一般的想法可能是,在changeState中加入switch块,这样会使得KnightContext过于繁重),而是把如何转换写在了SoldierState的transform方法中。这样就避免了在KnightContext中加入大量的切换状态的代码。如果需要新增加一个状态,只需要修改和增加SoldierState的子类即可。对于每一个状态,它都有一个单独的子类来表示,因此在状态多的情况下会出现很多个子类,这也是状态模式的缺点。
程序运行的结果为:
现在是弓箭模式。
现在是盾牌模式。
现在是步兵模式。
现在是弓箭模式。
现在是盾牌模式。
以上便是状态模式的说明,希望能够对大家有所帮助。