一种行为设计模式。
特点是用类的方式去管理状态。
优点:
- 对每个状态进行了封装,提高了代码的可维护性;
- 减少了条件判断语句的使用,降低维护成本;
- 易于扩展,每次新增状态都无需大规模修改其他类,符合开闭原则;
缺点:
- 会导致类的增加,每个状态都会是一个单独的类;
- 增加了性能的开销,状态的实例化会导致性能消耗增加。
用途:
- 设计游戏中人物的状态
- 设计网络连接时的状态
- 设计订单的状态
主要组成部分:
状态的接口:它定义了每个状态的实现规则。
每个状态的具体实现类:定义了状态的具体的实现逻辑和切换逻辑。
上下文(或者叫控制器):维护一个具体状态的引用,通常是指调用状态对象。
实例:
//状态的接口
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();
}
}
}