設計模式(22) 策略模式
阿新 • • 發佈:2020-09-19
在策略模式中,一個類的行為或演算法可以在執行時動態更改。
GOF對策略模式的描述為:
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients.
— Design Patterns : Elements of Reusable Object-Oriented Software
UML類圖如下:
策略模式包含三個角色:
- Context上下文角色,起承上啟下封裝作用,遮蔽高層模組對策略、演算法的直接訪問,封裝可能存在的變化。
- Strategy抽象策略角色,策略、演算法家族的抽象,通常為介面,定義每個策略或演算法必須具有的方法和屬性。
- ConcreteStrategy具體策略角色,實現抽象策略中的操作,該類含有具體的演算法。
程式碼示例:
以電商會員折扣為例,不同級別的會員享受的折扣是不同的,這種差異可以用策略模式來封裝。
public interface Strategy { double CalcPrice(double originalPrice); } public class PrimaryStrategy : Strategy { public double CalcPrice(double originalPrice) { return originalPrice; } } public class IntermediateStrategy : Strategy { public double CalcPrice(double originalPrice) { return originalPrice * 0.9; } } public class AdvancedStrategy : Strategy { public double CalcPrice(double originalPrice) { return originalPrice * 0.8; } } public class PriceContext { public Strategy Strategy { get; set; } public double GetPrice(double originalPrice) { return this.Strategy.CalcPrice(originalPrice); } }
呼叫端:
public class Test { public static void Entry() { Strategy strategy = new PrimaryStrategy(); PriceContext price = new PriceContext(); price.Strategy = strategy; Console.WriteLine(price.GetPrice(100)); //100 strategy = new IntermediateStrategy(); price.Strategy = strategy; Console.WriteLine(price.GetPrice(100)); //90 strategy = new AdvancedStrategy(); price.Strategy = strategy; Console.WriteLine(price.GetPrice(100)); //80 } }
示例中有若干具體的策略類,以及一個context物件,context物件會隨著策略物件的改變而變更其執行演算法。
策略模式的優點
- 演算法可以自由切換,只要實現抽象策略,它就成為策略家族的一個成員,通過封裝角色對其進行封裝,保證對外提供“可自由切換”的策略。
- 避免使用多重條件判斷,多重條件語句不易維護,而且出錯的概率較大。使用策略模式後,可以由其他模組決定採用何種策略,策略家族對外提供的訪問介面就是封裝類,簡化了操作,同時避免了條件語句判斷。
- 擴充套件性良好,在現有的系統中增加一個策略非常容易,只要實現介面就可以了。
策略模式的缺點
- 策略類數量增多,每一個策略都是一個類,複用的可能性很小,類數量增多。
- 所有的策略類都需要對外暴露,上層模組必須知道有哪些策略,並瞭解這些策略之間的區別,然後才能決定使用哪一個策略,這與迪米特法則是相違背的。
策略模式的適用場景
- 多個類只有在演算法或行為上稍有不同的場景。
- 演算法需要自由切換的場景。