設計模式-策略模式學習筆記
阿新 • • 發佈:2019-05-12
scan disco result 簡單 exceptio jpg alc discount 分享
前言:策略模式是和簡單工廠一起在幾天前學的,今晚有空正好寫下來
策略模式
策略模式是定義一組算法,將每一種算法都封裝成共同接口的獨立類中,讓它們之間可以互相替換,此模式讓算法的變化獨立於使用算法的客戶。
- 優缺點
優點:
- 滿足開放-封閉原則(擴展算法時,直接新增算法類,不用修改上下文)
- 降低了策略和策略調用者的耦合度
- 一個算法發生修改時,其他算法可以不用暴露
- 簡化了算法的單元測試
缺點:
- 每個算法獨立成類,算法越多,類越來越多
- 所有的策略類都用暴露出去,客戶端必須要知道所有的策略類
- 結構
Strategy:抽象的策略(一個借口或抽象類)
ConcreteStrategy:具體的策略(實現了Strategy的算法類)
Context:策略上下文(策略模式的上下文類,持有Strategy類的引用,也可將策略的參數放置在上下文類中)
- 代碼
引用《大話設計模式》中的例子,商場購物有優惠,現有優惠方案:1、打折 2、滿減,可能會有優惠方案:1、贈送積分
抽出父類策略類。
/** * @ Author :fonxi * @ Date :2019/5/10 2:56 * @ Description:策略類 */ public interface Super { Double count(Context ctx); }
然後將每一種優惠方案當做一種算法,獨立封裝成具體策略類。
/** * @ Author :fonxi * @ Date :2019/5/10 2:56 * @ Description:具體策略-折扣類 */ public class Discount implements Super{ @Override public Double count(Context ctx) { return ctx.getDiscountRate()*ctx.getMoney(); } }
/** * @ Author :fonxi * @ Date :2019/5/10 2:56 * @ Description:具體策略-返利類 */ public class Rebate implements Super{ @Override public Double count(Context ctx) { if(ctx.getMoney()>ctx.getRebateMoeny()){ return ctx.getMoney() - Math.floor(ctx.getMoney()/ctx.getRebateMoeny()) * ctx.getRebateValue(); } return ctx.getMoney(); } }
上下文中放置具體算法所需的參數,持有策略類的引用,並返回具體調用的策略算法。
/** * @ Author :fonxi * @ Date :2019/5/10 3:01 * @ Description:上下文 */ @Data public class Context {
//總金額 private Double money; //折扣 private Double discountRate; //到達額度 產生返利 private Double rebateMoeny; //返利值 private Double rebateValue; //持有一個策略對象 private Super superObject; public Context(Double rebateMoeny,Double rebateValue,Double money,Double discountRate,Super superObject){ this.rebateMoeny = rebateMoeny; this.rebateValue = rebateValue; this.money = money; this.discountRate = discountRate; this.superObject = superObject; } public Double getResult(Context ctx){ return superObject.count(ctx); } }
在客戶端,根據需求選擇不同的策略,然後通過策略上下文得到不同的策略實現。
/** * @ Author :fonxi * @ Date :2019/5/10 3:10 * @ Description:客戶端選擇類 */ public class Calculator { public void print(){ Scanner s = new Scanner(System.in); Context context = null; //折扣 Double discountRate = null; //到達額度 產生返利 Double rebateMoeny = null; //返利值 Double rebateValue = null; try { System.out.println("請輸入總金額"); Double money = s.nextDouble(); System.out.println("請選擇折扣方式:1、打折2、返利"); String type = s.next(); if(type.equals("1")){ System.out.println("請輸入折扣"); discountRate = s.nextDouble(); } else if(type.equals("2")){ System.out.println("請輸入滿減額度"); rebateMoeny = s.nextDouble(); System.out.println("請輸入滿減值"); rebateValue = s.nextDouble(); } Super superObject = null; switch (type){ case "1": superObject = new Discount(); break; case "2": superObject = new Rebate(); break; default: System.out.println("輸入選擇有誤"); break; } context = new Context(rebateMoeny,rebateValue,money,discountRate,superObject); System.out.println("結算金額是:"+context.getResult(context)); }catch (Exception e){ System.out.println("請輸入有誤"+e.getMessage()); } } }
- 總結
策略模式使得每種算法都能夠靈活的替換,並且在新增算法時不修改原有代碼,不管是耦合性還是可擴展性都被大大的優化了,不過在客戶端調用策略時會出現臃腫的選擇,需要通過其他方式去優化。
設計模式-策略模式學習筆記