在 C# 開發中,策略模式是一種經典的設計模式,它允許在運行時動態切換演算法,符合開閉原則。本文透過一道經典的 C# 上機題——約瑟夫環問題,展示如何應用策略模式優雅地解決問題。
題目要求:從第一個人開始報數,報到 3 的倍數者退出,循環進行直到剩下最後一人。這是一個典型的「約瑟夫環」問題。若直接用迴圈硬編碼,後續若需更換規則(如改為報 5 的倍數、雙向報數等),修改成本極高。
核心在於定義一個策略介面 IStrategy,並針對不同規則實現具體策略類別。主遊戲類別 Game 持有策略介面引用,透過事件通知遊戲結束。
public interface IStrategy
{
void Work(Game g);
}
public class StrategyA : IStrategy
{
private List<Person> over = new List<Person>();
private int k = 0;
public void Work(Game game)
{
foreach (Person p in game.Players)
{
p.Say(++k);
if (k % 3 == 0)
over.Add(p);
}
game.Players.RemoveAll(o => over.Contains(o));
}
}
Game 類別負責初始化玩家、設定策略、啟動遊戲迴圈,並在剩餘玩家數為 1 時觸發 GameOver 事件。
public class Game
{
public IStrategy Strategy { get; set; }
public List<Person> Players { get; set; }
public event EventHandler GameOver;
public Game(int num)
{
Players = new List<Person>();
for (int i = 0; i < num; i++)
Players.Add(new Person(i + 1));
}
public void Start()
{
if (Strategy != null)
{
while (Players.Count > 1)
Strategy.Work(this);
GameOver?.Invoke(Players.First().Id, EventArgs.Empty);
}
}
}
若需新增規則(如 StrategyB:報 5 的倍數),只需新增實現 IStrategy 的類別,完全不修改 Game 核心邏輯,完美體現「對擴展開放,對修改關閉」的設計原則。
策略模式將演算法封裝為獨立類別,使系統具備極佳的彈性與維護性。本例中,透過介面導向程式設計,輕鬆實現了規則的熱插拔,是 C# 面向對象設計的典範應用。