狀態(tài)模式(State): 在軟件開發(fā)過程中,應(yīng)用程序可能會(huì)根據(jù)不同的情況作出不同的處理。最直接的解決方案是將這些所有可能發(fā)生的情況全都考慮到,然后使用if else語(yǔ)句來做狀態(tài)判斷來進(jìn)行不同情況的處理。但對(duì)復(fù)雜狀態(tài)的判斷就顯得"力不從心了",隨著增加新的狀態(tài)或者修改一個(gè)狀體if else(或switch case)語(yǔ)句的增多或者修改)可能會(huì)引起很大的修改,違反OCP原則。狀態(tài)模式就是在當(dāng)控制一個(gè)對(duì)象狀態(tài)轉(zhuǎn)換的條件表達(dá)式過于復(fù)雜時(shí),把相關(guān)"判斷邏輯"提取出來,放到一系列的狀態(tài)類當(dāng)中,這樣可以把原來復(fù)雜的邏輯判斷簡(jiǎn)單化。 狀態(tài)模式的角色: 1)環(huán)境類(Context):也稱為上下文,它定義了客戶感興趣的接口,維護(hù)一個(gè)當(dāng)前狀態(tài),并將與狀態(tài)相關(guān)的操作委托給當(dāng)前狀態(tài)對(duì)象來處理。 2)抽象狀態(tài)類(AbstractState):定義一個(gè)接口以封裝與Context的一個(gè)特定狀態(tài)相關(guān)的行為。 3)具體狀態(tài)類(ConcreteState):實(shí)現(xiàn)抽象狀態(tài)所對(duì)應(yīng)的行為。 狀態(tài)模式的代碼實(shí)現(xiàn): 1 internal class Program 2 { 3 private static void Main(string[] args) 4 { 5 // Setup context in a state 6 Context c = new Context(new ConcreteStateA()); 7 8 // Issue requests, which toggles state 9 c.Request(); 10 c.Request(); 11 } 12 } 13 14 public abstract class AbstractState 15 { 16 public abstract void Handler(Context context); 17 } 18 19 public class Context 20 { 21 private AbstractState state; 22 23 public Context(AbstractState state) 24 { 25 this.state = state; 26 } 27 28 public AbstractState State 29 { 30 get 31 { 32 return state; 33 } 34 set 35 { 36 state = value; 37 Console.WriteLine("State: " + state.GetType().Name); 38 } 39 } 40 41 public void Request() 42 { 43 state.Handler(this); 44 } 45 } 46 47 public class ConcreteStateA : AbstractState 48 { 49 public override void Handler(Context context) 50 { 51 context.State = new ConcreteStateB(); 52 } 53 } 54 55 public class ConcreteStateB : AbstractState 56 { 57 public override void Handler(Context context) 58 { 59 context.State = new ConcreteStateC(); 60 } 61 } 62 63 public class ConcreteStateC : AbstractState 64 { 65 public override void Handler(Context context) 66 { 67 context.State = new ConcreteStateA(); 68 } 69 } 實(shí)例:(以電燈開關(guān)為例) 1 internal class Program 2 { 3 private static void Main(string[] args) 4 { 5 Light light = new Light(new LightOff()); 6 light.PressSwich(); 7 light.PressSwich(); 8 } 9 } 10 11 /// <summary> 12 /// 抽象電燈狀態(tài)類 13 /// </summary> 14 public abstract class LightState 15 { 16 public abstract void PressSwich(Light light); 17 } 18 19 public class Light 20 { 21 private LightState state; 22 23 public Light(LightState state) 24 { 25 this.state = state; 26 } 27 28 public LightState State 29 { 30 get { return state; } 31 set { state = value; } 32 } 33 34 public void PressSwich() 35 { 36 state.PressSwich(this); 37 } 38 } 39 40 /// <summary> 41 /// 電燈打開狀態(tài) 42 /// </summary> 43 public class LightOn : LightState 44 { 45 public override void PressSwich(Light light) 46 { 47 Console.WriteLine("Turn off the light."); 48 light.State = new LightOff(); 49 } 50 } 51 52 /// <summary> 53 /// 電燈關(guān)閉狀態(tài) 54 /// </summary> 55 public class LightOff : LightState 56 { 57 public override void PressSwich(Light light) 58 { 59 Console.WriteLine("Turn on the light."); 60 light.State = new LightOn(); 61 } 62 } 狀態(tài)模式的優(yōu)缺點(diǎn): 優(yōu)點(diǎn): 1)狀態(tài)模式將與特定狀態(tài)相關(guān)的行為局部化到一個(gè)狀態(tài)中,并且將不同狀態(tài)的行為分割開來,滿足“單一職責(zé)原則”。 2)減少對(duì)象間的相互依賴。將不同的狀態(tài)引入獨(dú)立的對(duì)象中會(huì)使得狀態(tài)轉(zhuǎn)換變得更加明確,且減少對(duì)象間的相互依賴。 3)有利于程序的擴(kuò)展。通過定義新的子類很容易地增加新的狀態(tài)和轉(zhuǎn)換。 缺點(diǎn): 1)狀態(tài)模式的使用必然會(huì)增加系統(tǒng)的類與對(duì)象的個(gè)數(shù)。 2)狀態(tài)模式的結(jié)構(gòu)與實(shí)現(xiàn)都較為復(fù)雜,如果使用不當(dāng)會(huì)導(dǎo)致程序結(jié)構(gòu)和代碼的混亂。 狀態(tài)模式的應(yīng)用場(chǎng)景: 1)當(dāng)一個(gè)對(duì)象的行為取決于它的狀態(tài),并且它必須在運(yùn)行時(shí)根據(jù)狀態(tài)改變它的行為。 2)一個(gè)操作中含有龐大的分支結(jié)構(gòu),并且這些分支決定于對(duì)象的狀態(tài)。 狀態(tài)模式與策略模式的區(qū)別: 從UML圖上我們會(huì)發(fā)現(xiàn)這兩種設(shè)計(jì)模式幾乎一摸一樣,都是利用多態(tài)把一些操作分配到一組相關(guān)的簡(jiǎn)單的類中。然而在顯示世界中,策略模式和狀態(tài)模式是兩種完全不同的思想。對(duì)狀態(tài)進(jìn)行建模時(shí),狀態(tài)遷移是一個(gè)核心問題;但策略模式與遷移毫無關(guān)系,策略模式允許一個(gè)客戶選擇或提供一種策略。 狀態(tài)模式與責(zé)任鏈模式的區(qū)別: 職責(zé)鏈模式和狀態(tài)模式都可以解決if分支過多的問題,從定義來看,狀態(tài)模式是一個(gè)對(duì)象內(nèi)在狀態(tài)發(fā)生改變(一個(gè)對(duì)象,相對(duì)穩(wěn)定,處理完一個(gè)對(duì)象下一個(gè)對(duì)象一般已確定),而職責(zé)鏈模式是多個(gè)對(duì)象之間的改變(多個(gè)對(duì)象之間的話,就會(huì)出現(xiàn)某個(gè)對(duì)象不存在的問題,且該模式由客戶端指定,不穩(wěn)定),這也說明了這兩個(gè)模式處理的情況不同。 |
|