策略模式+工廠模式+模板方法模式與spring的結合

一、現在有很多關於策略模式,工廠模式和模板方法的介紹。但是基本都是main方法來展示的,不太清楚怎麼移植到自己代碼中。這裏將其中if else當很多的時候,通過這三種模式與spring結合起來。

這個是當計算商品的價格時候,通過不同會員類型來計算,應該支付的價格的僞代碼。可以看到根據三種不同類型,擁有不同折扣。其實看到這個代碼,並不算麻煩。如果這一塊經常變動,這就會導致這個算法越來越臃腫,進而得到的後果就是代碼行數越來越多,開發人員改動一點點代碼都需要把所有功能全部都回歸一遍。下面通過幾種模式的運用,將這一塊解耦開來。

public BigDecimal quotePrice(BigDecimal orderPrice, String type) {

        if ("particularlyVip".equals(type)) {
            return orderPrice.multiply(new BigDecimal(0.95));
        }

        if ("Vip".equals(type)) {
            return orderPrice.multiply(new BigDecimal(0.9));
        }

        if ("Vip".equals(type)) {
            return orderPrice.multiply(new BigDecimal(0.8));
        }
     
        return orderPrice;
    }

首先定義一個service的接口,定義不同策略類。讓不同策略類實現計算價格的這一接口。

public interface UserPayService {

    /**
     * 計算應付價格
     */
    BigDecimal quotePrice(BigDecimal orderPrice);
}

定義一個抽象模板類,實現service和InitializingBean 接口,afterPropertiesSet用於註冊到工廠方法之中。這樣剩下的策略方法只用繼承UserPayTemplate ,實現quotePrice這個方法。

public abstract class UserPayTemplate implements UserPayService,InitializingBean {

    private String type;
    
    public UserPayTemplate(String type) {
        this.type = type;
    }

    @Override
    public  abstract  BigDecimal quotePrice(BigDecimal orderPrice);

    @Override
    public void afterPropertiesSet() throws Exception {
        UserPayStrategyFactory.register(type,this);
    }
}

三種策略方法,繼承抽象模板類去實現具體計算應付價格的具體邏輯。

@Service
public class ParticularlyVipPayService extends UserPayTemplate {

    private static final String type = "particularlyVip";

    public ParticularlyVipPayService() {
        super(type);
    }

    @Override
    public BigDecimal quotePrice(BigDecimal orderPrice) {
        return orderPrice.multiply(new BigDecimal(0.95));
    }
}

@Service
public class SuperVipPayService extends UserPayTemplate {
    private static final String type = "SuperVip";


    public SuperVipPayService() {
        super(type);
    }

    @Override
    public BigDecimal quotePrice(BigDecimal orderPrice) {
        return orderPrice.multiply(new BigDecimal(0.8));
    }
}

@Service
public class VipPayService extends UserPayTemplate {
    private static final String type = "Vip";

    public VipPayService() {
        super(type);
    }


    @Override
    public BigDecimal quotePrice(BigDecimal orderPrice) {
        return orderPrice.multiply(new BigDecimal(0.9));
    }
    
}

定義一個工廠方法,讓工廠方法與不同策略結合起來。在選擇不同策略的時候,通過工廠類來創造這個方法。

public class UserPayStrategyFactory {

    private static Map<String,UserPayService> services = new ConcurrentHashMap<String,UserPayService>();

    public  static UserPayService getByUserType(String type){
        return services.get(type);
    }

    public static void register(String userType,UserPayService userPayService){
        Assert.notNull(userType,"type can't be null");
        services.put(userType,userPayService);
    }
}

下面是Controller的測試方法,通過這種將數據庫裏面的數據和剛剛定義的不同策略結合起來,並查看測試結果。

 @PostMapping("/getRequest")
    public String testRequestBody(HttpServletRequest request, HttpServletResponse response) throws IOException {
   
        String type1 = "particularlyVip";
        UserPayService userPayService = UserPayStrategyFactory.getByUserType(type1);
        BigDecimal quote = userPayService.quotePrice(new BigDecimal(300));
        System.out.println("particularlyVip會員商品的最終價格爲:" + quote.doubleValue());
        String type2 = "Vip";
        UserPayService userPayService2 = UserPayStrategyFactory.getByUserType(type2);
        BigDecimal quote2 = userPayService2.quotePrice(new BigDecimal(300));
        System.out.println("vip會員商品的最終價格爲:" + quote2.doubleValue());
        String type3= "SuperVip";
        UserPayService userPayService3 = UserPayStrategyFactory.getByUserType(type3);
        BigDecimal quote3 = userPayService3.quotePrice(new BigDecimal(300));
        System.out.println("SuperVip會員商品的最終價格爲:" + quote3.doubleValue());
        return "success";
    }

測試結果:

particularlyVip會員商品的最終價格爲:285.0
vip會員商品的最終價格爲:270.0
SuperVip會員商品的最終價格爲:240.0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章