型態:行為模式(Behavioral Pattern)。
定義:當一個物件的內在狀態改變時允許改變其行為,這物件看起來像是改變了其類別。
使用時機: 當一個物件的行為取決於它的狀態,而且必須在執行時刻根據狀態改變它的行為時,就可以考慮使用狀態模式。
結構圖:來源
先來一個例子:參考
TrafficLight .cs |
using System.Threading; namespace ConsoleApplication1 { public class TrafficLight { private enum eState { Red, Green, Yellow }; private eState _State = eState.Red; public void Change() { switch (_State) { case eState.Red: Console.WriteLine("紅燈"); Sleep(5000); this._State = eState.Green; break; case eState.Green: Console.WriteLine("綠燈"); Sleep(5000); this._State = eState.Yellow; break; case eState.Yellow: Console.WriteLine("黃燈"); Sleep(5000); this._State = eState.Red; break; } } private void Sleep(int second) { try { Thread.Sleep(second); }catch{ throw; } } } } |
Program.cs |
class Program { static void Main(string[] args) { TrafficLight oTrafficLight = new TrafficLight(); oTrafficLight.Change(); oTrafficLight.Change(); oTrafficLight.Change(); Console.ReadKey(); } } |
輸出結果
我們觀察 TrafficLight .cs 類別裡個 Change 方法,若是增加多個燈號或是其他如方向的狀態變化時, 這樣的寫法將會增加更多層次的判斷。
可以考慮讓每個狀態各自成為一個物件,負責自己該狀態的服務,並提供切換裝態的方法
TrafficLight .cs |
/// <summary> /// 狀態介面。 /// </summary> public interface IState { void Change(TrafficLight light); } /// <summary> /// Light 抽象類別。 /// </summary> public abstract class Light : IState { public abstract void Change(TrafficLight light); protected void Sleep(int second) { try { Thread.Sleep(second); } catch {throw;} } } /// <summary> /// 黃燈類別。 /// </summary> public class Yellow : Light { public override void Change(TrafficLight light) { Console.WriteLine("黃燈"); Sleep(5000); light.set(new Red()); // 如果考慮彈性調整狀態,可以不用寫死狀態物件設定 } } /// <summary> /// 紅燈類別。 /// </summary> public class Green : Light { public override void Change(TrafficLight light) { Console.WriteLine("綠燈"); Sleep(5000); light.set(new Yellow()); // 如果考慮彈性調整狀態,可以不用寫死狀態物件設定 } } /// <summary> /// 紅燈類別。 /// </summary> public class Red : Light { public override void Change(TrafficLight light) { Console.WriteLine("紅燈"); Sleep(5000); light.set(new Green()); // 如果考慮彈性調整狀態,可以不用寫死狀態物件設定 } } /// <summary> /// 交通號誌類別。 /// </summary> public class TrafficLight { private IState current = new Red(); public void set(IState state) { this.current = state; } public void change() { current.Change(this); } } |
Program.cs |
TrafficLight trafficLight = new TrafficLight(); while (true) { trafficLight.change(); } |
輸出結果是一樣的
最後說明一下狀態模式的好處:
透過把各種狀態轉移邏輯分佈到 State 的子類別之間,來減少相互間的依賴。
0 Comments:
張貼留言