C#基礎(chǔ)State模式(行為型模式)

字號:

在軟件構(gòu)建過程中,考試大提示:某些對象的狀態(tài)如果改變,其行為也會(huì)隨之而發(fā)生變化,比如文檔處于只讀狀態(tài),其支持的行為和讀寫狀態(tài)支持的行為就可能完全不同,如何在運(yùn)行時(shí)根據(jù)對象的狀態(tài)來透明的更改對象行為?而不會(huì)為對象操作和狀態(tài)轉(zhuǎn)化之間引入緊耦合?
    意圖:
    允許一個(gè)對象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為。從而使對象看起來似乎修改了其行為
    public class Context
    {
    private State m_State;
    public Context(State state)
    {
    m_State = state;
    }
    public void ChangeState(State state)
    {
    m_State = state;
    }
    public void Handle()
    {
    m_State.Operate(this);
    }
    }
    public abstract class State
    {
    public abstract void Operate(Context ctx);
    }
    public class ConcreteStateA : State
    {
    public override void Operate(Context ctx)
    {
    Console.WriteLine("The State is processed By A");
    ctx.ChangeState(new ConcreteStateB());
    }
    }
    public class ConcreteStateB : State
    {
    public override void Operate(Context ctx)
    {
    Console.WriteLine("The State is processed By B");
    ctx.ChangeState(new ConcreteStateA());
    }
    }
    class Program
    {
    static void Main(string[] args)
    {
    State state = new ConcreteStateB();
    Context ctx = new Context(state);
    ctx.Handle();
    ctx.Handle();
    ctx.Handle();
    ctx.Handle();
    Console.Read();
    }
    }
    從上面的代碼來看,我們抽象了一個(gè)狀態(tài)機(jī)的基類State,他有個(gè)一個(gè)抽象方法Operate,通過這個(gè)方法的參數(shù)來間接的調(diào)用上下文的引用。我們在ConcreteStateA和ConcreteStateB中實(shí)現(xiàn)了Operate方法,并且在執(zhí)行一段代碼之后自動(dòng)切換到下一個(gè)狀態(tài),我們這里只存在兩種狀態(tài),所以他是互相切換的,我們可以添加多種狀態(tài),讓狀態(tài)一步步的切換。注意,狀態(tài)的切換不由Context來控制。在Context類中,我們保存了State的私有變量用來存儲(chǔ)當(dāng)前Context的狀態(tài)。ChangeState方法我們讓新的狀態(tài)替換原有的狀態(tài)引用,相當(dāng)于切換了狀態(tài)。Handle方法處理了客戶端的請求,并且State對象將操作自己對應(yīng)的方法。我們通過多態(tài)的概念來自動(dòng)調(diào)用對應(yīng)的Operate方法。在Operate方法中,我們也可以不用傳Context引用,但是我們在狀態(tài)切換的時(shí)候,很有可能要改變Context其他的屬性或行為,所以這個(gè)地方傳遞Context引用。Context的Handle方法我們只是在這里做個(gè)演示進(jìn)行互相切換,我們完全可以擴(kuò)充其他的方法,先切換一個(gè)狀態(tài),再來調(diào)用狀態(tài)的Operate方法。當(dāng)然State也可以擴(kuò)充其他的方法,表明Context其他內(nèi)容的變化
    考試大提示要點(diǎn):
    State模式將所有與一個(gè)特定狀態(tài)相關(guān)的行為都放入一個(gè)State的子類對象中,在對象狀態(tài)切換時(shí),切換響應(yīng)的對象;但同時(shí)維持State的接口,這樣實(shí)現(xiàn)了具體操作與狀態(tài)轉(zhuǎn)換之間的解藕。
    為不同的狀態(tài)引入不同的對象使得狀態(tài)轉(zhuǎn)換變得更加明確,而且可以保證不會(huì)出現(xiàn)狀態(tài)不一致的情況,因?yàn)檗D(zhuǎn)換是原子性的--即要么徹底轉(zhuǎn)換過來,要么不轉(zhuǎn)換
    如果State對象沒有實(shí)例變量,那么各個(gè)上下文可以共享同一個(gè)State對象,從而節(jié)省對象開銷。
    這種模式避免了我們寫大量的if else或switch case語句,但是很有可能會(huì)導(dǎo)致某些系統(tǒng)有過多的具體狀態(tài)類,并且由此導(dǎo)致開發(fā)人員可能會(huì)對所有的狀態(tài)類有所遺漏。