一種行為設計模式。
特點是用類的方式去管理狀態。
優點:
- 對每個狀態進行了封裝,提高了代碼的可維護性;
- 減少了條件判斷語句的使用,降低維護成本;
- 易于擴展,每次新增狀態都無需大規模修改其他類,符合開閉原則;
缺點:
- 會導致類的增加,每個狀態都會是一個單獨的類;
- 增加了性能的開銷,狀態的實例化會導致性能消耗增加。
用途:
- 設計游戲中人物的狀態
- 設計網絡連接時的狀態
- 設計訂單的狀態
主要組成部分:
狀態的接口:它定義了每個狀態的實現規則。
每個狀態的具體實現類:定義了狀態的具體的實現邏輯和切換邏輯。
上下文(或者叫控制器):維護一個具體狀態的引用,通常是指調用狀態對象。
實例:
//狀態的接口
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();}}
}