设计模式分为:创建型,结构型和行为型三种设计模式;
状态模式干货知识点
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;
}
}