GoF经典说明:
让一个对象随着内部状态的改变而改变,而该对象也像是换了类一样
模式说明:
当一个对象的状态发生改变的时候,对象行为也随之发生改变。但是这个对象对外的操作方式及信息沟通并不发生改变。对象的行为切换是通过内部状态类的切换而切换,当一个对象的内部状态从一个状态切换到另一个状态时,这个对象就会表现出这个状态下预定的行为。这个切换行为最好由状态自己确定,而不是由对象或者更高层的操纵者决定。否则会增加系统的复杂性及耦合性。对于进程而言,只需要知道这个对象对外公开的操作方式及信息沟通就可以了。
重要概念:
1.Context:状态拥有者,也是对象上下文。外界持有这个上下文去处理需求。
2.State:状态接口,规范Context在不同状态下的行为以及沟通方式
3.ConcreteState:实现每个状态下,Context具体的行为
案例分析:游戏场景切换
1.需求分析:
Unity制作游戏时,通常会将游戏不能功能区用场景进行区分,各场景之间的数据也极大的保持独立,游戏同一时间只持有一个场景运行。
2.功能实现流程分析:
客户端进程持有一个场景管理对象,流程图如下
游戏进程持有一个Context对象,Context对象持有一个State对象,初始化Context的时候指定一个State对象,作为初始场景。当每个State规定的行为发生变化时,State自己通知Context需要进行场景切换,切换方式为替换掉当前Context持有的State对象即可。
3.代码设计流程分析:
(1)游戏有三个场景:登陆场景(LoginSceneState)、主场景(MainSceneState)、战斗场景(BattleSceneState)
(2)当前场景需要执行的方法,场景初始化(Start),场景运行(Update),场景结束(End)
(3)当当前场景触发场景切换条件时,将需要切换的场景通知给Context,并节行切换。
(4)流程图设计
4.部分代码实现
(1)ISceneState 场景状态接口,使用抽象类
//场景状态得到场景控制器,方便在状态中直接进行场景切换,不污染上层代码
private SceneController mController;
//场景名称,Unity根据这个名称加载场景
//正式环境中尽量不要public变量,而是要根据需求公开需要的读或者写权利,通过属性实现
public string mSceneName;
public ISceneState(SceneController controller,string sceneName ){
mController = controller;
mSceneName = sceneName;
}
//场景初始化
public virtual void start(){
//TODO
}
//主逻辑执行,比如NPC及主角的创建,死亡,AI等等
public virtual void update(){
//TODO
}
//场景结束
public virtual void end(){
//TODO
}
//场景切换,由于只在状态内部执行,所以设为protected级别
protected virtual void changeSceneState(ISceneState targetState ){
//这里只传入controller,接口构造函数中的需要的name,在每一个具体实现类中指定
this.mController.changeState(targetState);
}
//重载toString()方法,方便追踪调试
public override string ToString(){
return String.fromat("[SceneState:{0}]",mSceneName);
}
(2)SceneController 场景控制器
private SceneState mSceneState;
public void changeState( ISceneState state ){
//处理一下当前场景结束前需要干的事,比如释放资源等,
//注意这里还要处理很多事,比如场景空判断,场景异步加载等等,这里是简单描述
mSceneState.end();
//改变状态
mSceneState = state;
//处理一下当前状态初始化方法
mSceneState.start();
}
//场景运行时逻辑调用
public void update(){
this.mSceneState.update();
}
通过以上代码,大家可以清晰的发现,各个场景之间的逻辑不在互相干扰,中控Controller只需要实现场景切换的逻辑,而不需要关具体的场景下一个切换对象是什么。某些只在特定场景运行模块系统也变得独立起来。
后面还有一种有限状态机FSM,广泛用于游戏内AI功能,后续也会有写