1. 程式人生 > >在商城系統中使用設計模式----策略模式之在spring中使用策略模式

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

這樣的 control actor case imp bean 支付 wire 問題

1.前言:

這是策略模式在spring中的使用,對策略模式不了解對同學可以移步在商城中簡單對使用策略模式。

2.問題:

在策略模式中,我們創建表示各種策略的對象和一個行為,隨著策略對象改變而改變的 context 對象。策略對象改變 context 對象的執行算法。

在spring 中,策略對象在正常情況下是,在啟動Spring容器對時候,已經將策略對象加載創建完成成為bean。

我們如何在Spring中正確對使用策略模式,這樣又會發生什麽問題呢?

3.使用場景: 

場景:商城活動中有幾種,滿減,打折,送積分.我們要獲取商品對最終價格。

4.實現

步驟一.創建接口類

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吧。

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