C#狀態模式——解決方法過長問題


         上週進京趕考GCT(碩士專業學位研究生入學資格考試),需要提前動身去看考場,順便和同伴一起在北京找個酒店住下,安頓好之後,當躺下的之後筆者想的不是第二天如何應考,而是腦袋了充滿了狀態,狀態,狀態,狀態模式,可能這幾天和小夥伴們討論設計模式比較多緣故吧。此文是爲記錄當時的想法,之後加以聯繫以前所學並實踐後寫出來的。

一、概述

         1.摘要:

          狀態模式允許一個對象在其內部狀態改變時改變它的行爲,使對象看起來似乎修改了它的類。

         2.解決的問題:

          在軟件開發過程中,應用程序可能會根據不同的情況作出不同的處理。最直接的解決方案是將這些所有可能發生的情況全都考慮到,然後使用(if else(switch case)語句來做狀態判斷來進行不同情況的處理。但是編程中如果一個方法中有很多判斷就是壞味道了。假如我有10個、100個狀態,如果還是用(if else(switch case)來做判斷那豈不是會累死?再假如我需要增加或修改一個狀態,可能得需要大刀闊斧地進行修改,而程序的可讀性、擴展性也會變得很弱,稍一部小心可能就會出錯,維護起來也會很麻煩。這下我們就可以考慮使用狀態模式解決此問題,只修改自身的狀態即可。

         3.結構如下:

                                                

Conetext:維護一個ConcreteState子類的實例,它可以定義當前的狀態。

State:定義了一個所有具體狀態的共同接口,也可以是抽象類,任何狀態都實現這個相同的接口,這樣一來,狀態之間可以相互替換。

ConcreteState:處理來自Context的請求。每一個ConcreteState都提供了它自己對於請求的實現,所以,當Context狀態發生改變時行爲它也跟着改變。具體的狀態可以有很多個。



二、實踐

         可能僅看以上概念會比較難理解,接下來就看在考前的所想的一個簡單的例子——電燈。我們都知道電燈有兩種狀態,一個狀態是開燈,一個狀態是關燈,默認的狀態下電燈是關着的。

1.結構:

                            

2.代碼實現:

         首先,定義一個實現電燈狀態的接口

namespace LightState
{
    //定義狀態接口
    public interface LightState
    {
        void PressSwitch(Light llight);
    }
}

         其次,定義電燈的具體狀態——開燈和關燈

/***********************************************
      '類 名 稱:LightOn
      '創建時間:2015/10/29 13:23:30
      '作    者:覃仕珍	
      '說    明:開燈狀態
 ************************************************/
namespace LightState
{
    public class LightOn : LightState
    {
        public void PressSwitch(Light light)
        {
            Console.WriteLine("關燈");
            light.State = new LightOff(); //設置電燈的下一個狀態爲關燈狀態
        }
    }
}


/***********************************************
      '類 名 稱:LightOff
      '創建時間:2015/10/29 13:28:35
      '作    者:覃仕珍	
      '說    明:關燈狀態
 ************************************************/
namespace LightState
{
    public class LightOff : LightState
    {
        public void PressSwitch(Light light)
        {
            Console.WriteLine("開燈");
            light.State = new LightOn();
        }
    }
}

         第三,定義擁有開燈和關燈狀態的對象,即電燈

/***********************************************
      '類 名 稱:Light
      '創建時間:2015/10/29 13:18:40
      '作    者:覃仕珍	
      '說    明:定義擁有開燈和關燈狀態的對象,即電燈
 ************************************************/
namespace LightState
{
    public class Light
    {
        public LightState State;
        public Light()
        {
            State = new LightOff();   //另一個狀態爲關燈
        }

        public void PressSwitch()
        {
            State.PressSwitch(this);  //設置燈的初始狀態爲關燈
        }
    }
}

         最後,看結果

namespace LightState
{
    public class Program
    {
        static void Main(string[] args)
        {
            Light light = new Light();
            //調用的順序與在電燈對象中設置是有關係的
            light.PressSwitch();  //開燈
            light.PressSwitch();  //關燈
            light.PressSwitch();   //開燈
            light.PressSwitch();  //關燈

            Console.ReadLine();
        }
    }
}

         運行結果如下:

                    

         當“電燈”發出請求改變狀態的時候,不管它發出的是什麼請求(開燈或是關燈),在具體的子類裏都有自己的實現,而且可以相互替換,所以不管你是按下的開燈還是關燈都可以達到你想要的效果。那天不知怎的,開燈的時候突然就想起了狀態模式,回來之後就做了這個簡單的例子實踐了一下,真是應了那句話:實踐出真知。以前僅看HeadFirst上的講解,似懂非懂,動動小手指就明白了許多。


三、狀態模式 VS 策略模式


       最近和慶波、子傑兄討論了23個設計模式,感覺和兩位大神一起自己收穫還是很大的。實踐了設計模式之後感覺狀態模式與策略模式簡直是一對孿生兄弟,主要是因爲它們的類圖是一樣的,但細細看還是有很大的差別的。狀態模式是狀態在滿足一定條件下的自動更換,用戶無法指定狀態,最多隻能設置初始狀態,而策略模式是讓用戶指定更換的策略算法,也就是一次只能選擇一種策略算法。

                                 

     就先簡單瞭解到這兒了,如果大神們還有什麼建議,懇請留言,筆者感激不盡。








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章