策略設(shè)計(jì)模式:動態(tài)切換算法的藝術(shù)(C#實(shí)現(xiàn))
策略設(shè)計(jì)模式是一種行為型設(shè)計(jì)模式,它允許在運(yùn)行時從算法族中選擇特定算法。通過將算法單獨(dú)封裝并使其可互換,該模式能幫助我們創(chuàng)建靈活、可復(fù)用的代碼,而無需修改現(xiàn)有代碼結(jié)構(gòu)。
無策略模式時的問題
若不使用策略模式,我們通常需要依賴條件語句(if-else或switch-case)來決定使用哪種算法或方法。這種方式會導(dǎo)致:
? 代碼重復(fù):在代碼庫的不同位置出現(xiàn)多重條件判斷
? 維護(hù)困難:添加新策略需要修改現(xiàn)有代碼
? 違反開閉原則:每次引入新算法都需要修改類
? 缺乏可復(fù)用性:算法與使用它們的類緊密耦合
無策略模式的示例
using System;
publicclassPaymentService
{
public void ProcessPayment(string paymentType)
{
if (paymentType == "CreditCard")
{
Console.WriteLine("Processing payment via Credit Card");
}
elseif (paymentType == "PayPal")
{
Console.WriteLine("Processing payment via PayPal");
}
elseif (paymentType == "Crypto")
{
Console.WriteLine("Processing payment via Cryptocurrency");
}
else
{
Console.WriteLine("Invalid payment method");
}
}
}
classProgram
{
static void Main()
{
PaymentService paymentService = new PaymentService();
paymentService.ProcessPayment("CreditCard");
}
}
上述代碼的問題
1. 添加新支付方式需要修改ProcessPayment方法
2. 類與支付處理邏輯緊密耦合
3. 難以單獨(dú)測試每種支付方式
C#實(shí)現(xiàn)策略模式
為解決這些問題,我們可以使用策略模式重構(gòu)代碼。
第一步:定義策略接口
創(chuàng)建支付策略接口:
public interface IPaymentStrategy
{
void ProcessPayment();
}
第二步:實(shí)現(xiàn)具體策略
每個支付方法都作為獨(dú)立的類實(shí)現(xiàn)IPaymentStrategy接口:
public classCreditCardPayment : IPaymentStrategy
{
public void ProcessPayment()
{
Console.WriteLine("Processing payment via Credit Card");
}
}
publicclassPayPalPayment : IPaymentStrategy
{
public void ProcessPayment()
{
Console.WriteLine("Processing payment via PayPal");
}
}
publicclassCryptoPayment : IPaymentStrategy
{
public void ProcessPayment()
{
Console.WriteLine("Processing payment via Cryptocurrency");
}
}
第三步:創(chuàng)建上下文類
上下文類持有策略引用并委托執(zhí)行:
public class PaymentContext
{
private IPaymentStrategy _paymentStrategy;
public PaymentContext(IPaymentStrategy paymentStrategy)
{
_paymentStrategy = paymentStrategy;
}
public void ProcessPayment()
{
_paymentStrategy.ProcessPayment();
}
}
第四步:在主程序中使用策略模式
class Program
{
static void Main()
{
IPaymentStrategy paymentMethod = new PayPalPayment();
PaymentContext paymentContext = new PaymentContext(paymentMethod);
paymentContext.ProcessPayment();
}
}
策略模式的現(xiàn)實(shí)應(yīng)用
? 支付處理系統(tǒng):不同支付網(wǎng)關(guān)(信用卡、PayPal、加密貨幣等)
? 排序算法:動態(tài)選擇不同排序技術(shù)
? 壓縮庫:應(yīng)用不同壓縮算法(ZIP、GZIP、RAR等)
? 認(rèn)證策略:支持不同認(rèn)證機(jī)制(OAuth、JWT、SAML等)
? 日志框架:允許不同日志策略(文件日志、控制臺日志、數(shù)據(jù)庫日志等)
策略模式的優(yōu)點(diǎn)
遵循開閉原則:無需修改現(xiàn)有代碼即可添加新策略
提高代碼復(fù)用性:不同支付策略可重復(fù)使用
增強(qiáng)可維護(hù)性:支付邏輯與PaymentContext類分離
便于單元測試:每個策略可獨(dú)立測試
策略模式的缺點(diǎn)
? 增加復(fù)雜性:需要更多類
? 對象創(chuàng)建開銷:需要創(chuàng)建策略類的新實(shí)例
? 不適用于簡單場景:若只有2-3種策略,簡單的switch-case可能就足夠
何時使用策略模式?
? 當(dāng)你有多個相關(guān)算法且需要動態(tài)切換時
? 當(dāng)你想消除復(fù)雜的條件語句時
? 當(dāng)你想將算法邏輯與主業(yè)務(wù)邏輯分離時
? 當(dāng)你需要提高代碼的可維護(hù)性和可測試性時
策略模式是動態(tài)處理多種算法的有效方式,能顯著提升代碼組織性和靈活性。雖然它增加了一定的復(fù)雜性,但極大地增強(qiáng)了可維護(hù)性,是處理需要多種可互換行為的系統(tǒng)時的理想選擇。