設計模式分爲:創建型,結構型和行爲型三種設計模式;
狀態模式乾貨知識點
1、狀態模式屬於行爲型設計模式。
2、狀態模式(State):當一個對象的內在狀態改變時允許改變其行爲,這個對象看起來像是改變了其類。
3、解決內容:狀態模式主要解決的是當控制一個對象狀態轉換的條件表達式過於複雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類中,可以把複雜的判斷邏輯簡化。
4、優點:將與特定狀態相關的行爲局部化,並且將不同狀態的行爲分割開來。
5、使用場景:
5.1、當一個對象的行爲取決於它的狀態,並且它必須在運行時時刻根據狀態改變它的行爲樹,就可以考慮使用狀態模式了。
5.2、一個操作中含有龐大的多分支的條件語句,且這些分支依賴於該對象的狀態。這個狀態通常用一個或多個枚舉常量表示。通常, 有多個操作包含這一相同的條件結構。S t a t e模式將每一個條件分支放入一個獨立的類中。這使得你可以根據對象自身的情況將對象的狀態作爲一個對象,這一對象可以不依賴於其他對象而獨立變化。
狀態模式的結構圖:
1、一個狀態基類,多個不同狀態實現
2、一個狀態上下文
狀態模式案例1:遊戲角色AI狀態切換
/// <summary>
/// 抽象狀態基類
/// </summary>
public abstract class FSMState
{
public int stateId;
public abstract void EnterState(BaseFsm fsm);
public abstract void ExitState();
public abstract void Action();
public abstract void Check();
}
/// <summary>
/// 狀態1:攻擊中
/// </summary>
public class AttackingState : FSMState
{
public override void EnterState(BaseFsm fsm)
{
Debug.Log("進去攻擊狀態");
}
public override void ExitState(){}
public override void Check(){}
public override void Action()
{
Debug.Log("播放攻擊動畫");
}
}
/// <summary>
/// 狀態2:待機中
/// </summary>
public class IdleState : FSMState
{
public override void EnterState(BaseFsm fsm)
{
Debug.Log("進入待機狀態");
}
public override void ExitState(){}
public override void Check(){}
public override void Action()
{
Debug.Log("播放待機動畫");
}
}
/// <summary>
/// 狀態3:死亡
/// </summary>
public class DeadState : FSMState
{
public override void EnterState(BaseFsm fsm)
{
Debug.Log("進入死亡狀態");
Debug.Log("播放死亡動畫");
}
public override void ExitState(){}
public override void Check(){}
public override void Action()
{
}
}
/// <summary>
/// 狀態模式上下文,擁有狀態,可切換狀態,
/// </summary>
public class BaseFsm
{
public FSMState state;
public void Init()
{
state.EnterState(this);
}
public void ChangeState(int stateId)
{
//通過id找到對應狀態
// state = this.FindState(stateId);
state.EnterState(this);
}
}
public class Client
{
public void Main()
{
BaseFsm fsm = new BaseFsm();
fsm.Init();
fsm.ChangeState(1);
}
}
狀態模式案例2:水池開放狀態和關閉狀態的切換
/// <summary>
/// 抽象狀態基類
/// </summary>
abstract class State
{
protected string stateName;
abstract public void Pour();
// do something state-specific here
}
/// <summary>
/// 狀態1:打開出水
/// </summary>
class OpenedState : State
{
public OpenedState ()
{
stateName = "Opened";
}
override public void Pour()
{
Console.WriteLine("...pouring...");
Console.WriteLine("...pouring...");
Console.WriteLine("...pouring...");
}
}
/// <summary>
/// 狀態2:關閉
/// </summary>
class ClosedState : State
{
public ClosedState()
{
stateName = "Closed";
}
override public void Pour()
{
Console.WriteLine("ERROR - bottle is closed - cannot pour");
}
}
/// <summary>
/// 上下文
/// </summary>
class ContextColaBottle
{
/// <summary>
/// 狀態枚舉
/// </summary>
public enum EBottleStateType
{
Closed,
Opened
};
// If teh state classes had large amounts of instance data,
// we could dynamically create them as needed - if this demo
// they are tiny, so we just create them as data members
public ContextColaBottle ()
{
// Initialize to closed
CurrentState = new ClosedState();
}
private State CurrentState;
public void SetState(EBottleStateType newState)
{
switch(newState)
{
case EBottleStateType.Closed:
CurrentState = new ClosedState();
break;
case EBottleStateType.Opened:
CurrentState = new OpenedState();
break;
}
}
//出水
public void Pour()
{
CurrentState.Pour();
}
}
/// <summary>
/// Summary description for Client.
/// </summary>
public class Client
{
public static int Main(string[] args)
{
ContextColaBottle contextColaBottle = new ContextColaBottle();
Console.WriteLine("initial state is closed");
Console.WriteLine("Now trying to pour");
contextColaBottle.Pour();
Console.WriteLine("Open bottle");
contextColaBottle.SetState(ContextColaBottle.EBottleStateType.Opened);
Console.WriteLine("Try to pour again");
contextColaBottle.Pour();
return 0;
}
}