型態:行為模式(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:
張貼留言