在商城系統中使用設計模式----策略模式之在spring中使用策略模式

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;

    }
}

 

源碼:

在springboot中使用策略模式

 

 

 在工做中,不能靈活的時候設計模式。但願經過此次的學習,能夠加深對設計模式對理解。

接下來會繼續整理出本身在工做對時候可使用對設計模式,不對望指點。若是文章對您有幫助,github給個start吧。

相關文章
相關標籤/搜索