大話設計模式學習筆記-策略模式
阿新 • • 發佈:2018-11-24
策略模式
它定義了演算法家族,分別封裝起來,讓他們之間可以互相替換,此模式讓演算法的變化不會影響到使用演算法的客戶。
優點
策略模式是一種定義了一系列演算法的方法,從個概念上看,所有這些演算法完成的都是相同的工作。只是實現不同。他可以以相同的方式呼叫所有的演算法,減少了各種演算法類與使用演算法類之間的耦合。
策略模式優化了單元測試,因為每個演算法都有自己的類,可以通過自己的介面單獨測試。
不足
策略模式就是用來封裝演算法的,選擇具體實現的職責由客戶端物件承擔,並轉給策略模式的Context物件,這本身並沒有接觸客戶端需要選擇判斷的壓力。不過和簡單工廠模式結合後,選擇具體實現的職責也可以由Context來承擔。
策略模式結構演示
父類:Strategy
定義所有支援的演算法的公共介面,為Context定義了一系列的可重用的演算法或行為,繼承有助於析取出這些演算法中的公共功能。
abstract class Strategy{ public abstract void AlgorithmInterface(); }
子類:ConcreteStrategy
封裝了具體的演算法或行為,繼承Strategy
class ConcreteStrategyA:Strategy{ public override void AlgorithmInterface(){ Console.WriteLine("演算法A實現"); } } class ConcreteStrategyB:Strategy{ public override void AlgorithmInterface(){ Console.WriteLine("演算法B實現"); } } class ConcreteStrategyC:Strategy{ public override void AlgorithmInterface(){ Console.WriteLine("演算法C實現"); } }
上下文類:Context
用一個ConcreteStrategy來配置,維護一個對Strategy物件的引用
class Context{ Strategy strategy; //初始化物件 public Context(Strategy strategy)=>this.strategy=strategy; //呼叫具體的策略 public void ContextInterface()=>strategy.AlgorithmInterface(); }
測試類:Program
class Program{ static void Main(string[] args){ Context context; context = new Context(new ConcreteStrategyA()); context.ContextInterface(); context = new Context(new ConcreteStrategyB()); context.ContextInterface(); context = new Context(new ConcreteStrategyC()); context.ContextInterface(); Console.Read(); } }
測試結果:控制檯
演算法A實現
演算法B實現
演算法C實現
使用策略模式改進商場促銷
上下文類:CashContext
增加上下文類。通過呼叫上下文類,傳入上下文類不同的策略來實現不同的演算法或行為
class CashContext{ private CashSuper cs; public CashContext(CashSuper csuper) => cs = csuper; public double GetResult(double money) => cs.AcceptCash(money); }
測試類:Program
修改測試類
class Program { static void Main(string[] args){ Console.Write("請輸入商品單價:"); double foodSprice=double.Parse(Console.ReadLine()); Console.Write("請輸入商品數量:"); double fooeNum = double.Parse(Console.ReadLine()); Console.WriteLine($"1:原價{Environment.NewLine}2:八折{Environment.NewLine}3:滿300返100"); Console.Write("請選擇優惠方式:"); CashContext cc = null; switch (Console.ReadLine()){ case "1": cc = new CashContext(new CashNormal()); break; case "2": cc = new CashContext(new CashRebate(0.8)); break; case "3": cc = new CashContext(new CashReturn(300,100)); break; } Console.WriteLine(cc.GetResult(foodSprice*fooeNum)); Console.ReadKey(); } }
使用策略模式和簡單工廠模式結合改進商場促銷
策略模式和簡單工廠模式的結合,使客戶端只需要認識一個上下文類即可,降低耦合性。
雖然Context裡還是用到了switch,但是可以使用反射技術解決,在抽象工廠模式中對此有詳細講解。
上下文類:CashContext
改進CashContext,將演算法的選擇在上下文類構造方法中完成,建立好對應的例項。
class CashContext { private CashSuper cs; public CashContext(string type){ switch (type){ case "1": cs = new CashNormal(); break; case "2": cs = new CashRebate(0.8); break; case "3": cs = new CashReturn(300, 100); break; } } public double GetResult(double money) => cs.AcceptCash(money); }
測試類:Program
將具體的收費演算法與客戶端徹底分離,更加簡潔明瞭。
class Program{ static void Main(string[] args){ Console.Write("請輸入商品單價:"); double foodSprice=double.Parse(Console.ReadLine()); Console.Write("請輸入商品數量:"); double fooeNum = double.Parse(Console.ReadLine()); Console.WriteLine($"1:原價{Environment.NewLine}2:八折{Environment.NewLine}3:滿300返100"); Console.Write("請選擇優惠方式:"); var csuper = new CashContext(Console.ReadLine()); Console.WriteLine(csuper.GetResult(foodSprice*fooeNum)); Console.ReadKey(); } }