【设计模式C#】状态模式(用于解决解耦多种状态之间的交互)
一种行为设计模式。
特点是用类的方式去管理状态。
优点:
- 对每个状态进行了封装,提高了代码的可维护性;
- 减少了条件判断语句的使用,降低维护成本;
- 易于扩展,每次新增状态都无需大规模修改其他类,符合开闭原则;
缺点:
- 会导致类的增加,每个状态都会是一个单独的类;
- 增加了性能的开销,状态的实例化会导致性能消耗增加。
用途:
- 设计游戏中人物的状态
- 设计网络连接时的状态
- 设计订单的状态
主要组成部分:
状态的接口:它定义了每个状态的实现规则。
每个状态的具体实现类:定义了状态的具体的实现逻辑和切换逻辑。
上下文(或者叫控制器):维护一个具体状态的引用,通常是指调用状态对象。
实例:
//状态的接口
using UnityEngine;/// <summary>
/// 每个场景的状态接口类
/// </summary>
public abstract class ISceneState
{ private string mSceneName;//场景名称protected SceneStateController mController;//场景状态控制器public ISceneState(string sceneName, SceneStateController controller){mSceneName = sceneName;mController = controller;}public string SceneName{get { return mSceneName; }}/// <summary>/// 状态开始时调用/// </summary>public virtual void StateStart() { }/// <summary>/// 状态结束时调用/// </summary>public virtual void StateEnd() { }/// <summary>/// 状态更新时调用/// </summary>public virtual void StateUpdate() { }
}
//状态的实现类
using UnityEngine;
using UnityEngine.UI;public class StartState: ISceneState
{public StartState(SceneStateController controller) :base("01StartScene", controller){}private Image mLOGO;private float mSmoothingTime = 1f;//LOGO过渡时间private float mWaitTime = 2f;//进入MainMenue前等待时间public override void StateStart(){mLOGO = GameObject.Find("Canvas/LOGO").GetComponent<Image>();mLOGO.color = Color.black;}public override void StateUpdate(){//LOGO图片的缓冲过渡mLOGO.color = Color.Lerp(mLOGO.color, Color.white, mSmoothingTime * Time.deltaTime);//等待时间mWaitTime -= Time.deltaTime;//LOGO图片的缓冲过渡if(mWaitTime <= 0){mController.SetState(new MainMenuState(mController));}}
}
//状态的实现类
using UnityEngine;
using UnityEngine.UI;public class MainMenuState: ISceneState
{public MainMenuState(SceneStateController controller): base("02MainMenuScene", controller){}public override void StateStart(){GameObject.Find("Canvas/StartButton").GetComponent<Button>().onClick.AddListener(StartGameButtonOnClick);}public void StartGameButtonOnClick(){mController.SetState(new BattleState(mController));}
}
//状态的实现类
public class BattleState: ISceneState
{public BattleState(SceneStateController controller): base("03BattleScene", controller){}public override void StateStart(){GameFacade.Instance.Init();}public override void StateEnd(){GameFacade.Instance.Release();}public override void StateUpdate(){ if(GameFacade.Instance.isGameOver){mController.SetState(new MainMenuState(mController));}GameFacade.Instance.Update();}
}
//上下文(或者叫控制器):
using UnityEngine;
using UnityEngine.SceneManagement;public class SceneStateController
{private ISceneState mState;//当前场景状态private AsyncOperation mAO;//异步加载场景private bool mIsRunStart = false;//表示场景是否已经正在运行中/// <summary>/// 设置场景状态/// </summary>/// <param name="state">状态</param>/// <param name="isLoadScene">是否加载场景</param>public void SetState(ISceneState state, bool isLoadScene = true){ //退出状态时的处理if(mState != null){mState.StateEnd();}//设置新状态mState = state;//加载场景if(isLoadScene){mAO = SceneManager.LoadSceneAsync(mState.SceneName);mIsRunStart = false;}else{mState.StateStart();mIsRunStart = true;}}/// <summary>/// 更新场景状态/// </summary>public void StateUpdate(){if (mAO != null && mAO.isDone == false) return;if(mIsRunStart == false && mAO != null && mAO.isDone == true){mState.StateStart();mIsRunStart = true;}if(mIsRunStart && mState != null){mState.StateUpdate();}}
}