首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 策略模式完全指南:演算法封裝與動態切換實戰

     編輯:關於C#

前言

當系統需要在執行時根據條件動態切換演算法或行為時,若使用大量 if-else 或 switch-case 判斷,會導致程式碼難以維护、違反開閉原則。策略模式提供了一種優雅方案:定義一系列演算法,將各自封裝起來,並使它們可以互相替換。本文透過訊息儲存系統(SQL vs XML)完整展示策略模式在 C# 中的實作精髓。

模式結構與核心角色

本範例展示兩種可互換的持久化策略:

  • Strategy(策略介面):IMessageStrategy,定義 Get()、Insert(MessageModel) 契約。
  • ConcreteStrategy(具體策略):SqlMessage、XmlMessage,實作不同儲存邏輯。
  • Context(環境角色):Message 類別,持有策略參考,委派操作給策略物件,提供統一介面給客戶端。
策略模式類別圖

核心程式碼實作詳解

1. 策略介面:定義演算法契約

public interface IMessageStrategy
{
    List<MessageModel> Get();
    bool Insert(MessageModel mm);
}

介面隔離了演算法的「做什麼」與「怎麼做」,使具體策略可獨立演化。

2. 具體策略:封裝差異化邏輯

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; }
}

每個策略類別專注單一儲存方式,符合單一職責原則。

3. Context 角色:委派與切換核心

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 方法支援執行時切換)。
  • Context 不需知道具體策略細節,只依賴抽象介面。
  • 客戶端決定使用哪種策略,Context 僅負責委派。

4. 客戶端動態切換展示

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 類別。

進階應用與最佳實務

策略的選擇與注入時機

  • 建構子注入:策略在物件生命週期固定,如本範例。
  • Setter 注入:需執行時動態切換策略,提供 SetStrategy(IMessageStrategy) 方法。
  • 方法參數傳遞:單次操作使用不同策略,如 Execute(IMessageStrategy strategy)。

避免策略類別爆炸

  • 若策略僅有微小差異,考慮使用「模板方法模式」在基類別封裝共同邏輯,策略類別只覆寫差異步驟。
  • 結合「工廠模式」根據條件建立策略,將策略建立邏輯從客戶端分離。

策略模式 vs 狀態模式

兩者結構相似但意圖不同:

  • 策略模式:客戶端主動選擇演算法,策略之間通常無關係,強調「可替換性」。
  • 狀態模式:物件內部狀態改變驅動行為變化,狀態之間可能有轉換邏輯,強調「狀態驅動行為」。

優缺點總結

優點

  • 演算法與使用者分離,符合單一職責與開閉原則。
  • 避免大量條件判斷,程式碼更清晰。
  • 支援執行時動態切換演算法。
  • 策略類別可獨立測試、複用。

缺點

  • 策略類別數量增加,可能導致類別膨脹。
  • 客戶端必須了解所有策略才能正確選擇。
  • 若策略介面頻繁變動,會影響所有策略實作與 Context。

總結

策略模式是「組合優於繼承」原則的典型應用。本範例以訊息儲存系統為例,展示如何將 SQL、XML 兩種持久化演算法封裝為獨立策略類別,透過 Message Context 類別委派操作,實現客戶端零修改下的演算法動態切換。實務中廣泛應用於:付款方式選擇(信用卡、PayPal、Line Pay)、排序演算法切換、壓縮格式選擇、路由演算法等場景。掌握策略模式,能讓你在面對「多種演算法可選、需動態切換」的業務需求時,設計出高內聚、低耦合、易擴展的系統架構。


參考資源:DoFactory Strategy Pattern

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved