說明:
一物件有多個狀態,在不同狀態下有不同的行為。
一般可能會用多個 if else 來處理這些分支行為。
若使用狀態模式,則是將這些分支行為,提取出來,放到另外的 class 處理。
也就是將 if else 拆開,改寫成一個分支一個 class。
這樣做的優點是,複雜的 if else 分支,維護可能較麻煩。
用狀態模式,修改或新增分支時,則只需要修改相關的幾個分支類別即可。
範例:
遊戲中,玩家的等級不同,有不同的稱呼。
假設等級 0~20 => 新手,20~50 => 老手,50~90 => 高手,90 以上=> 神
希望達成如下的效果
static void Main(string[] args)
{
Player user = new Player();
user.level = 1; // 玩家等級
user.stateWork(); // 玩家狀態處理
user.level = 20;
user.stateWork();
user.level = 62;
user.stateWork();
user.level = 93;
user.stateWork();
Console.ReadLine();
}
執行結果: 等級 1 (新手)
等級 20 (老手)
等級 62 (高手)
等級 93 (神)
實現重點在於,將每個 if else 改寫成多個單獨的分支類別。
若符合條件的不是某個分支類別,則繼續將流程丟給下一個分支類別處理。
其餘程式碼
// 玩家類別,有一個等級的屬性
public class Player
{
public int level = 1; // 等級
/* 狀態處理,一般用 if else 的寫法
public void stateWork()
{
if (level >= 1 && level < 20)
{
Console.WriteLine("等級 {0} ({1})", level, "新手");
}
else if (level >= 20 && level < 50)
{
Console.WriteLine("等級 {0} ({1})", level, "老手");
}
else if (level >= 50 && level < 90)
{
Console.WriteLine("等級 {0} ({1})", level, "高手");
}
else if (level >= 90)
{
Console.WriteLine("等級 {0} ({1})", level, "神");
}
}
*/
// 將狀態處理改為以下寫法 (狀態模式)
private StateContext state;
public Player()
{
// 初始化狀態處理的物件
setStateContext(new ConcreteState001());
}
// 設定狀態處理的物件
public void setStateContext(StateContext s)
{
state = s;
}
// 狀態處理,轉交由 StateContext 物件處理
public void stateWork()
{
state.stateWork(this);
}
}
// 狀態模式的抽象類別
public abstract class StateContext
{
public abstract void stateWork(Player user);
}
// 等級 1~20
public class ConcreteState001 : StateContext
{
public override void stateWork(Player user)
{
if (user.level < 20)
{
Console.WriteLine("等級 {0} ({1})", user.level, "新手");
}
else
{
user.setStateContext(new ConcreteState050());
user.stateWork();
}
}
}
// 等級 20~50
public class ConcreteState050 : StateContext
{
public override void stateWork(Player user)
{
if (user.level < 50)
{
Console.WriteLine("等級 {0} ({1})", user.level, "老手");
}
else
{
user.setStateContext(new ConcreteState090());
user.stateWork();
}
}
}
// 等級 50~90
public class ConcreteState090 : StateContext
{
public override void stateWork(Player user)
{
if (user.level < 90)
{
Console.WriteLine("等級 {0} ({1})", user.level, "高手");
}
else
{
user.setStateContext(new ConcreteStateMAX());
user.stateWork();
}
}
}
// 等級 90~
public class ConcreteStateMAX : StateContext
{
public override void stateWork(Player user)
{
if (user.level >= 90)
{
Console.WriteLine("等級 {0} ({1})", user.level, "神");
}
}
}
相關連結:設計模式整理列表
沒有留言:
張貼留言