1.前言:html
這是策略模式在spring中的使用,對策略模式不瞭解對同窗能夠移步在商城中簡單對使用策略模式。git
2.問題:github
在策略模式中,咱們建立表示各類策略的對象和一個行爲,隨着策略對象改變而改變的 context 對象。策略對象改變 context 對象的執行算法。算法
在spring 中,策略對象在正常狀況下是,在啓動Spring容器對時候,已經將策略對象加載建立完成成爲bean。spring
咱們如何在Spring中正確對使用策略模式,這樣又會發生什麼問題呢?數據庫
3.使用場景: 設計模式
場景:商城活動中有幾種,滿減,打折,送積分.咱們要獲取商品對最終價格。springboot
4.實現app
步驟一.建立接口類 ide
public interface GoodsActivity { /** * 獲取應該支付的金額 * @param amount 商品的單價 * @return */ BigDecimal getPayPrice(BigDecimal amount); }
步驟二.實現接口,並添加@Component註解
@Component public class DiscountActivity implements GoodsActivity { //折扣 private double discount ; @Override public BigDecimal getPayPrice(BigDecimal amount) { //僞裝從數據庫的配置表取折扣 discount = 8.0; return new BigDecimal(discount).multiply(amount).divide(new BigDecimal(10)); } }
@Component public class FullReduceActivity implements GoodsActivity { //滿多少 private BigDecimal fullAmount; //減多少 private BigDecimal reductionAmount ; @Override public BigDecimal getPayPrice(BigDecimal amount) { //僞裝從數據庫的配置表取配置數據 fullAmount = new BigDecimal(300); reductionAmount = new BigDecimal(100); return amount.compareTo(fullAmount)>=0?amount.subtract(reductionAmount):amount; } }
@Component public class IntegralActivity implements GoodsActivity { //抵扣的積分 10積分=1元 private int integral = 100; @Override public BigDecimal getPayPrice(BigDecimal amount) { return amount.subtract(new BigDecimal(integral/10)); } }
步驟三.建立context
public class GoodsActivityContext { private GoodsActivity goodsActivity; public GoodsActivityContext(GoodsActivity goodsActivity){ this.goodsActivity=goodsActivity; } /** * 獲取商品價格 * @param amount * @return */ public BigDecimal getPrice(BigDecimal amount){ return goodsActivity.getPayPrice(amount); } }
步驟四.在控制層中調用策略模式
@RestController public class ActivityController{ @Autowired private DiscountActivity discountActivity; @Autowired private FullReduceActivity fullReduceActivity; @Autowired private IntegralActivity integralActivity; /** * 獲取最終售價 * (這樣的控制層寫法很不友好,須要寫大量的代碼去實現) * 爲了解決這個問題,將引用工廠模式... * * 工廠是建立型模式,它的做用就是建立對象; * 策略是行爲型模式,它的做用是讓一個對象在許多行爲中選擇一種行爲; * * 解決不一樣的問題 * 工廠模式是建立型的設計模式,它接受指令,建立出符合要求的實例;它主要解決的是資源的統一分發,將對象的建立徹底獨立出來,讓對象的建立和具體的使用客戶無關。主要應用在多數據庫選擇,類庫文件加載等。 * 策略模式是爲了解決的是策略的切換與擴展,更簡潔的說是定義策略族,分別封裝起來,讓他們之間能夠相互替換,策略模式讓策略的變化獨立於使用策略的客戶。 * * 工廠至關於黑盒子,策略至關於白盒子; * * * @param activityType * @param amount * @return */ @RequestMapping("getLastPrice") public ResponseResult getLastPrice(String activityType,BigDecimal amount){ ResponseResult responseResult = ResponseResult.getInstance(); GoodsActivityContext goodsActivityContext; //根據活動類型獲取最終售價 switch (activityType){ case "discount": goodsActivityContext = new GoodsActivityContext(discountActivity); break; case "fullReduce": goodsActivityContext = new GoodsActivityContext(fullReduceActivity); break; case "integral": goodsActivityContext = new GoodsActivityContext(integralActivity); break; default: responseResult.setCode(1); responseResult.setMsg("數據類型錯誤"); responseResult.setData(null); return responseResult; } responseResult.setCode(0); responseResult.setMsg("操做成功"); responseResult.setData(goodsActivityContext.getPrice(amount)); return responseResult; } }
總結:按照註釋說明,很明顯咱們須要優化這個策略模式。
步驟三:(2) 引入工廠模式,對策略對象進行管理
@Component public class GoodsActivityStrategyFactory { @Autowired private Map<String,GoodsActivity> goodsActivityMap; /** * 根據活動類型 獲取所對應的策略 * @param activityType */ public GoodsActivityContext getGoodsActivityStrategy(String activityType){ GoodsActivityContext goodsActivityContext; switch (activityType){ case "discount": goodsActivityContext = new GoodsActivityContext(goodsActivityMap.get("discountActivity")); break; case "fullReduce": goodsActivityContext = new GoodsActivityContext(goodsActivityMap.get("fullReduceActivity")); break; case "integral": goodsActivityContext = new GoodsActivityContext(goodsActivityMap.get("integralActivity")); break; default: goodsActivityContext = null; } return goodsActivityContext; } }
步驟四.在控制層中調用策略模式
@RestController public class ActivityController{ @Autowired private GoodsActivityStrategyFactory goodsActivityStrategyFactory; @RequestMapping("getLastPrice_V2") public ResponseResult getLastPrice_V2(String activityType,BigDecimal amount){ ResponseResult responseResult = ResponseResult.getInstance(); //從工廠中獲取 活動策略 GoodsActivityContext goodsActivityContext = goodsActivityStrategyFactory.getGoodsActivityStrategy(activityType); if (goodsActivityContext==null){ responseResult.setCode(1); responseResult.setData(null); responseResult.setMsg("數據類型錯誤"); return responseResult; } responseResult.setCode(0); responseResult.setMsg("操做成功"); responseResult.setData(goodsActivityContext.getPrice(amount)); return responseResult; } }
源碼:
在工做中,不能靈活的時候設計模式。但願經過此次的學習,能夠加深對設計模式對理解。
接下來會繼續整理出本身在工做對時候可使用對設計模式,不對望指點。若是文章對您有幫助,github給個start吧。
原文出處:https://www.cnblogs.com/boychen/p/10721078.html