目錄
- 定義與特點
- 結構與實作
- 模式的結構
- 模式的實作
- 應用場景
- 擴展:引入享元模式
在軟體開發程序中,應用程式中的有些物件可能會根據不同的情況做出不同的行為,我們把這種物件稱為有狀態的物件,而把影響物件行為的一個或多個動態變化的屬性稱為狀態,當有狀態的物件與外部事件產生互動時,其內部狀態會發生改變,從而使得其行為也隨之發生改變,
對這種有狀態的物件編程,傳統的解決方案是:將這些所有可能發生的情況全都考慮到,然后使用 if-else 陳述句來做狀態判斷,再進行不同情況的處理,但當物件的狀態很多時,程式會變得很復雜,而且增加新的狀態要添加新的 if-else 陳述句,這違背了“開閉原則”,不利于程式的擴展,
以上問題如果采用“狀態模式”就能很好地得到解決,狀態模式的解決思想是:當控制一個物件狀態轉換的條件運算式過于復雜時,把相關“判斷邏輯”提取出來,放到一系列的狀態類當中,這樣可以把原來復雜的邏輯判斷簡單化,
定義與特點
狀態(State)模式的定義:對有狀態的物件,把復雜的“判斷邏輯”提取到不同的狀態物件中,允許狀態物件在其內部狀態發生改變時改變其行為,
狀態模式是一種物件行為型模式,其主要優點如下:
- 狀態模式將與特定狀態相關的行為區域化到一個狀態中,并且將不同狀態的行為分割開來,滿足“單一職責原則”,
- 減少物件間的相互依賴,將不同的狀態引入獨立的物件中會使得狀態轉換變得更加明確,且減少物件間的相互依賴,
- 有利于程式的擴展,通過定義新的子類很容易地增加新的狀態和轉換,
狀態模式的主要缺點如下:
- 狀態模式的使用必然會增加系統的類與物件的個數,
- 狀態模式的結構與實作都較為復雜,如果使用不當會導致程式結構和代碼的混亂,
結構與實作
狀態模式把受環境改變的物件行為包裝在不同的狀態物件里,其意圖是讓一個物件在其內部狀態改變的時候,其行為也隨之改變,
模式的結構
狀態模式包含以下主要角色:
- 環境(Context)角色:也稱為背景關系,它定義了客戶感興趣的介面,維護一個當前狀態,并將與狀態相關的操作委托給當前狀態物件來處理,
- 抽象狀態(State)角色:定義一個介面,用以封裝環境物件中的特定狀態所對應的行為,
- 具體狀態(Concrete State)角色:實作抽象狀態所對應的行為,
其結構圖如圖所示:

模式的實作
狀態模式的實作代碼如下:
class Program
{
static void Main(string[] args)
{
Context context=new Context(); //創建環境
context.Handle(); //處理請求
context.Handle();
context.Handle();
context.Handle();
Console.Read();
}
}
//環境類
public class Context
{
private State state;
//定義環境類的初始狀態
public Context()
{
this.state=new ConcreteStateA();
}
//設定新狀態
public void SetState(State state)
{
this.state=state;
}
//讀取狀態
public State GetState()
{
return(state);
}
//對請求做處理
public void Handle()
{
state.Handle(this);
}
}
//抽象狀態類
public abstract class State
{
public abstract void Handle(Context context);
}
//具體狀態A類
public class ConcreteStateA : State
{
public override void Handle(Context context)
{
Console.WriteLine("當前狀態是 A.");
context.SetState(new ConcreteStateB());
}
}
//具體狀態B類
public class ConcreteStateB : State
{
public override void Handle(Context context)
{
Console.WriteLine("當前狀態是 B.");
context.SetState(new ConcreteStateA());
}
}
程式運行結果如下:
當前狀態是 A.
當前狀態是 B.
當前狀態是 A.
當前狀態是 B.
應用場景
通常在以下情況下可以考慮使用狀態模式:
- 當一個物件的行為取決于它的狀態,并且它必須在運行時根據狀態改變它的行為時,就可以考慮使用狀態模式,
- 一個操作中含有龐大的分支結構,并且這些分支決定于物件的狀態時,
擴展:引入享元模式
在有些情況下,可能有多個環境物件需要共享一組狀態,這時需要引入享元模式,將這些具體狀態物件放在集合中供程式共享,其結構圖如圖所示:

分析:共享狀態模式的不同之處是在環境類中增加了一個 HashMap 來保存相關狀態,當需要某種狀態時可以從中獲取,其程式代碼如下:
class Program
{
static void Main(string[] args)
{
ShareContext context=new ShareContext(); //創建環境
context.Handle(); //處理請求
context.Handle();
context.Handle();
context.Handle();
Console.Read();
}
}
//享元環境類
public class ShareContext
{
private ShareState state;
private Dictionary<String, ShareState> stateDic=new Dictionary<String, ShareState>();
public ShareContext()
{
state=new ConcreteState1();
stateDic.Add("1", state);
state=new ConcreteState2();
stateDic.Add("2", state);
state=GetState("1");
}
//設定新狀態
public void SetState(ShareState state)
{
this.state=state;
}
//讀取狀態
public ShareState GetState(String key)
{
ShareState s=stateDic[key];
return s;
}
//對請求做處理
public void Handle()
{
state.Handle(this);
}
}
//抽象狀態類
public abstract class ShareState
{
public abstract void Handle(ShareContext context);
}
//具體狀態1類
public class ConcreteState1 : ShareState
{
public override void Handle(ShareContext context)
{
Console.WriteLine("當前狀態是: 狀態1");
context.SetState(context.GetState("2"));
}
}
//具體狀態2類
public class ConcreteState2 : ShareState
{
public override void Handle(ShareContext context)
{
Console.WriteLine("當前狀態是: 狀態2");
context.SetState(context.GetState("1"));
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/1062.html
標籤:設計模式
上一篇:行為型模式之責任鏈模式
