状态模式,顾名思义,在于状态以及切换。比较常用的就是状态机,一个游戏角色在空闲,移动,攻击等状态相互切换时,就可以用状态模式。从一种行为转化为另一种行为的过程都在游戏内部实现,玩家不需要理解这个转化过程。而且无论怎么转化,玩家都是控制的该角色,并不会因为其内部的转变而有所差异。
另外虽然游戏角色会从空闲切换到攻击等状态,它的“表现行为”会有所变化,但是对于客户端来说,并不会因为这样的变化,而改变对它的“操作方法”的方式,也就是从开发角度说,这个对象对外界的对应方式不会有任何改变。但是对象的内部确实是会通过“更换状态类对象”的方式来进行状态的转换。
来看下状态模式的结构图:
(懒得画图了,自己找了个。与后续代码有些不同,不过整体结构是一样的)
其中:
[successbox title=”Context”]状态的拥有者,可以制定相关的接口,让外界能够得知状态的改变或通过操作让状态改变。[/successbox] [infobox title=”State”]状态接口类,规范Context在特定状态下要表现的行为。[/infobox] [infobox title=”StartState等”]具体状态类,实现Context在特定状态下该有的行为。比如角色空闲状态,攻击状态等。[/infobox]代码实现
Context:
class Context
{
private IState state; // 代表当前状态
// 更改状态
public void SetState(IState state)
{
this.state = state;
}
// 状态行为
public void Run()
{
if (state != null)
{
state.Handle();
}
}
} IState
抽象类,通过构造方法传入Context,以便后续操作中使用。并定义了一个抽象方法,使其在子类中实现。
abstract class IState
{
protected Context context;
public IState(Context context)
{
this.context = context;
}
public abstract void Handle();
} 3个State
class StateA : IState
{
public StateA(Context context) : base(context)
{
}
public override void Handle()
{
Console.WriteLine("已切换到StateA");
context.SetState(new StateB(context));
}
}
class StateB : IState
{
public StateB(Context context) : base(context)
{
}
public override void Handle()
{
Console.WriteLine("已切换到StateB");
context.SetState(new StateC(context));
}
}
class StateC : IState
{
public StateC(Context context) : base(context)
{
}
public override void Handle()
{
Console.WriteLine("已切换到StateC");
context.SetState(new StateA(context));
}
} 上述三个子类都实现了父类的抽象方法,用来表示在各自状态下的行为。这里为了演示,只做了最简单的切换状态功能。
Context类中提供了SetState方法用来让外界切换状态,而这个“外界”也可以是另一个State。所以实现上,状态的切换可以有一下两种方式:
- 交由Context类本身,按条件在各状态之间切换;
- 产生Context类对象时,马上指定初始状态给Context对象,而后在后续执行过程中的状态转换则交由State对象负责,Context对象不再介入。
测试代码:
static void Main(string[] args)
{
Context context = new Context();
context.SetState(new StateA(context));
context.Run();
context.Run();
context.Run();
context.Run();
} 结果如下:
结论
使用状态模式的优点:
1.减少错误的发生并降低维护难度;
不再使用switch来判断状态,在后续更新维护时如果需要新的功能(状态),直接从IState派生就可以了,符合了开闭原则。
2.状态执行环境单一化;
与每一个状态有关的对象及操作都被实现在一个场景状态下,符合单一职责原则。
3.项目之间可以共享,增强可复用性。
参考资料:《设计模式与游戏完美开发》




