定義
允許一個對象在其狀態改變時,改變它的行為。看起來對象似乎修改了它的類。
解決問題
State模式主要解決的是在開發中時常遇到的根據不同的狀態需要進行不同的處理操作的問題。解決這種問題,最一般的方法是採用switch-case語句進 行處理的,這樣會造成一個問題:分支過多,而且如果加入一個新的狀態就需要對原來的代碼進行編譯。
State模式採用了對這些不同的狀態進行封裝的方式處 理這類問題,當狀態改變的時候進行處理然後再切換到另一種狀態,也就是說把狀態的切換責任交給了具體的狀態類去負責.
State模式與Strategy模式比較:
State模式和 Strategy模式有很多相似的地方,需要說明的是兩者的思想都是一致的,只不過封裝的東西不同:State模式封裝的是不同的狀態,而Stategy 模式封裝的是不同的演算法。
涉及的角色
內容物件:定義了目前狀態,並能根據請求改變當前的狀態。
抽象狀態:定義了一個封裝上下文特定狀態切換的介面
具體狀態:每一個具體狀態實現特定的狀態切換方法。
狀態模式的關鍵:不同狀態所具有的行為介面相同。
類圖
實現代碼
namespace Hbb0b0.DesignPatter
{
/// <summary>
/// 內容物件
/// </summary>
public class StateContext
{
/// <summary>
/// 狀態
/// </summary>
private AbstractState state;
public AbstractState State
{
get { return state; }
set {
state = value;
Console.WriteLine("State: " + state.GetType().Name);
}
}
/// <summary>
/// 上下文建構函式
/// </summary>
/// <param name="state"></param>
public StateContext(AbstractState state)
{
//注意不要用this.state=state,如果寫成這樣就不會觸發狀態改變的
//控制台輸出
this.State = state;
}
/// <summary>
/// 請求改變狀態
/// </summary>
public void Request()
{
state.Handle(this);
}
}
}
namespace Hbb0b0.DesignPatter
{
/// <summary>
/// 抽象狀態
/// </summary>
public abstract class AbstractState
{
/// <summary>
/// 狀態切換
/// </summary>
/// <param name="context">內容物件</param>
abstract public void Handle(StateContext context);
}
}
namespace Hbb0b0.DesignPatter
{
/// <summary>
/// 具體狀態B
/// </summary>
public class ConcreteStateA : AbstractState
{
/// <summary>
/// 具體狀態切換A-->B
/// </summary>
/// <param name="context">內容物件</param>
public override void Handle(StateContext context)
{
context.State = new ConcreteStateB();
}
}
}
namespace Hbb0b0.DesignPatter
{
/// <summary>
/// 狀態B
/// </summary>
public class ConcreteStateB : AbstractState
{
/// <summary>
/// 具體狀態切換B-->C
/// </summary>
/// <param name="context">內容物件</param>
public override void Handle(StateContext context)
{
context.State = new ConcreteStateC();
}
}
}
namespace Hbb0b0.DesignPatter
{
/// <summary>
/// 狀態C
/// </summary>
public class ConcreteStateC : AbstractState
{
/// <summary>
/// 具體狀態切換B-->C
/// </summary>
/// <param name="context">內容物件</param>
public override void Handle(StateContext context)
{
context.State = new ConcreteStateA();
}
}
}
調用代碼
namespace Hbb0b0.DesignPatter
{
class StateMain
{
static internal void Run()
{
//用A狀態初始化上下文
StateContext stateContext = new StateContext(new ConcreteStateA ());
//上下文請求狀態改變
stateContext.Request();
//上下文請求狀態改變
stateContext.Request();
//上下文請求狀態改變
stateContext.Request();
//上下文請求狀態改變
stateContext.Request();
//上下文請求狀態改變
stateContext.Request();
}
}
}
運行結果
思考:以上類中添加了狀態D,如何??
類圖如下
具體的實現代碼就不寫了,當具體的環境中添加了新狀態ConcreteStateD, ConcreteStateE, ConcreteStateF時,由現有的類別關係圖可以體會出使用State模式的強大功能。