上週進京趕考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個設計模式,感覺和兩位大神一起自己收穫還是很大的。實踐了設計模式之後感覺狀態模式與策略模式簡直是一對孿生兄弟,主要是因爲它們的類圖是一樣的,但細細看還是有很大的差別的。狀態模式是狀態在滿足一定條件下的自動更換,用戶無法指定狀態,最多隻能設置初始狀態,而策略模式是讓用戶指定更換的策略算法,也就是一次只能選擇一種策略算法。
就先簡單瞭解到這兒了,如果大神們還有什麼建議,懇請留言,筆者感激不盡。