策略模式(Strategy):它定義了算法家族,分別封裝起來,讓他們之間可以互相替換,此模式讓算法的變化不會影響到使用算法的客戶。
策略模式是一種定義一系列算法的方法,從概念上來看,所有這些算法完成的都是相同的工作,只是實現不同,它可以以相同的方式調用所有的算法,減少了各種算法類與使用算法類之間的耦合。事實上你可以將一個繼承自抽象策略類的稱為具體策略,就是策略模式中的策略1,策略2......
策略模式的優點:
策略模式的Strategy類層次為Context定義了一系列的可供重用的算法或行為。繼承有助於析取出這些算法的公共功能。策略模式的另一個優點是簡化了單元測試,因為每個算法都有自己的類,可以通過自己的接口單獨測試。
說了這么多,策略模式究竟解決的是什么問題呢?
策略模式就是用來封裝算法的,但在實踐中,我們發現可以用它來封裝幾乎任何類型的規則,只要在分析過程中聽到需要在不同時間應用不同的業務規則,就可以考慮使用策略模式處理這種變化的可能性。
在基本策略模式中,選擇所用具體實現的職責由客戶端對象承擔,並轉給策略模式的Context對象。
策略模式的結構圖:
策略模式的具體實現代碼示例:
namespace 策略模式 { public class Program { static void Main(string[] args) { Console.WriteLine("我釣了一條魚,應該怎么煮呢?"); Context context; context = new Context(new ConcreteStrategyA()); //客戶端依賴具體實現類了 context.RunMethod(); context = new Context(new ConcreteStrategyB()); context.RunMethod(); Console.ReadKey(); } } //抽象算法類 public abstract class Strategy { //算法方法 public abstract void AlgorithmInterface(); } //具體策略1 public class ConcreteStrategyA : Strategy { public override void AlgorithmInterface() { Console.WriteLine("加水、上蒸籠、開火、清蒸!"); } } //具體策略2 public class ConcreteStrategyB : Strategy { public override void AlgorithmInterface() { Console.WriteLine("熱鍋、放油、紅燒!"); } } //上下文 public class Context { Strategy strategy; //構造方法接收具體對象 public Context(Strategy strategy) { this.strategy = strategy; } //調用方法 public void RunMethod() { strategy.AlgorithmInterface(); } } }
以上代碼感覺到了什么?策略模式不管創建,它做的事非常少,少到什么程度?
你傳個對象給我,我幫你調用這個對象的方法(這個工作主要通過Context來維護),我不管你這對象怎么創建,但你得給我個對象。策略模式不管對象的創建,那么它實質上是什么。用類圖說明。
從上面的類圖看到一個問題。因為,我調用你時,我要給你傳個對象,上面的例子直接new()。因此,客戶端依賴於具體實現類了。
所以,策略模式通常與一些創建對象的模式混合使用,比如負責維護調用具體策略的Context類搭配個簡單工廠:
public class Context { Strategy strategy = null; //調用方法 public void RunMethod(string type) { switch (type) { default: case "清蒸": strategy = new ConcreteStrategyA(); break; case "紅燒": strategy = new ConcreteStrategyB(); break; } strategy.AlgorithmInterface(); } }
這樣外部就依賴Context類了:
static void Main(string[] args) { Console.WriteLine("我釣了一條魚,應該怎么煮呢?"); Context context = new Context(); context.RunMethod("清蒸"); context.RunMethod("紅燒"); Console.ReadKey(); }
最后回顧一下:
策略模式不管對象創建,它的目的在於封裝不同的算法,根據傳入的對象,調用具體的策略方法,在上面的示例程序加入簡單工廠模式的原因,是因為要創建對應的具體類,要分清哪些代碼屬於哪個模式的范疇。
搞了半天,策略模式就是一個類封裝一個算法,實現一個算法接口,然后搞個Context來調用這些算法。