當系統需要在執行時根據條件動態切換演算法或行為時,若使用大量 if-else 或 switch-case 判斷,會導致程式碼難以維护、違反開閉原則。策略模式提供了一種優雅方案:定義一系列演算法,將各自封裝起來,並使它們可以互相替換。本文透過訊息儲存系統(SQL vs XML)完整展示策略模式在 C# 中的實作精髓。
本範例展示兩種可互換的持久化策略:
IMessageStrategy,定義 Get()、Insert(MessageModel) 契約。SqlMessage、XmlMessage,實作不同儲存邏輯。Message 類別,持有策略參考,委派操作給策略物件,提供統一介面給客戶端。
public interface IMessageStrategy
{
List<MessageModel> Get();
bool Insert(MessageModel mm);
}
介面隔離了演算法的「做什麼」與「怎麼做」,使具體策略可獨立演化。
SqlMessage 與 XmlMessage 分別實作 SQL 與 XML 儲存邏輯:
public class SqlMessage : IMessageStrategy
{
public List<MessageModel> Get()
{
var l = new List<MessageModel>();
l.Add(new MessageModel("SQL方式獲取Message", DateTime.Now));
return l;
}
public bool Insert(MessageModel mm) { /* SQL 插入邏輯 */ return true; }
}
每個策略類別專注單一儲存方式,符合單一職責原則。
Message 類別為客戶端提供穩定介面,內部委派給策略物件:
public class Message
{
private IMessageStrategy _strategy;
public Message(IMessageStrategy strategy)
{
this._strategy = strategy;
}
public List<MessageModel> Get() => _strategy.Get();
public bool Insert(MessageModel mm) => _strategy.Insert(mm);
}
關鍵設計:
SetStrategy 方法支援執行時切換)。Message m = new Message(new XmlMessage()); // 選擇 XML 策略
m.Insert(new MessageModel("插入", DateTime.Now));
var result = m.Get(); // XML方式獲取Message
m = new Message(new SqlMessage()); // 切換至 SQL 策略
m.Insert(new MessageModel("插入", DateTime.Now));
result = m.Get(); // SQL方式獲取Message
True
XML方式獲取Message 2007-2-10 22:42:44
True
SQL方式獲取Message 2007-2-10 22:42:44
同一組客戶端程式碼,透過注入不同策略物件,獲得完全不同的執行行為,且無需修改 Message 類別。
SetStrategy(IMessageStrategy) 方法。Execute(IMessageStrategy strategy)。兩者結構相似但意圖不同:
策略模式是「組合優於繼承」原則的典型應用。本範例以訊息儲存系統為例,展示如何將 SQL、XML 兩種持久化演算法封裝為獨立策略類別,透過 Message Context 類別委派操作,實現客戶端零修改下的演算法動態切換。實務中廣泛應用於:付款方式選擇(信用卡、PayPal、Line Pay)、排序演算法切換、壓縮格式選擇、路由演算法等場景。掌握策略模式,能讓你在面對「多種演算法可選、需動態切換」的業務需求時,設計出高內聚、低耦合、易擴展的系統架構。