如何將業務代碼寫得像詩同樣(使用註解+單例+工廠去掉一大波if和else判斷)

1.訂單控制器,提供一個根據商品id和銀行渠道id計算商品折後價格的接口:java

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;

@RestController
@RequestMapping("/order")
public class OrderController {

    /**
     * 根據商品id和銀行渠道id計算折扣後的金額
     *
     * @param goodsId   商品id
     * @param channelId 銀行渠道id
     * @return
     */
    @GetMapping("/calc")
    @ResponseBody
    public String calcAmount(Integer goodsId, Integer channelId) {
        Context context = new Context();
        BigDecimal bigDecimal;
        try {
            bigDecimal = context.calRecharge(goodsId, channelId);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        return bigDecimal.setScale(2) + "";
    }
}

 

2.上下文:web

import java.math.BigDecimal;

public class Context {

    /**
     * 根據商品id和銀行渠道id計算折扣後的金額
     *
     * @param goodsId   商品id
     * @param channelId 銀行渠道id
     * @return
     * @throws Exception
     */
    public BigDecimal calRecharge(Integer goodsId, Integer channelId) throws Exception {
        StrategyFactory strategyFactory = StrategyFactory.getInstance();
        // 根據渠道id查詢具體的銀行實現類
        Strategy strategy = strategyFactory.create(channelId);
        // 調用具體的實現類進行計算
        return strategy.calRecharge(goodsId, channelId);
    }
}

 

3.折扣計算單例工廠類,內部用一個Map來存儲銀行渠道id和具體銀行實現類之間的映射關係,方便根據渠道id反射獲取對應銀行具體的實現類:spring

import org.reflections.Reflections;

import java.util.HashMap;
import java.util.Set;

public class StrategyFactory {
    private static StrategyFactory strategyFactory = new StrategyFactory();

    private StrategyFactory() {
    }

    public static StrategyFactory getInstance() {
        return strategyFactory;
    }

    private static HashMap<Integer, String> source_map = new HashMap<>();

    static {
        Reflections reflections = new Reflections("ICBCBankImpl");
        Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(Pay.class);
        for (Class<?> clazz : classSet) {
            Pay pay = clazz.getAnnotation(Pay.class);
            source_map.put(pay.channelId(), clazz.getCanonicalName());
        }
    }

    /**
     * 根據銀行渠道id從Map中獲取具體的銀行實現類
     *
     * @param channelId
     * @return
     * @throws Exception
     */
    public Strategy create(int channelId) throws Exception {
        String clazz = source_map.get(channelId);
        Class<?> clazz_ = Class.forName(clazz);
        return (Strategy) clazz_.newInstance();
    }
}

 

4.計算折後價格的接口:數據庫

import java.math.BigDecimal;

public interface Strategy {
    BigDecimal calRecharge(Integer goodsId, Integer channelId);
}

 

5.工商銀行實現類,類上加上@Pay註解指定工商銀行對應的數據庫中的渠道id:app

import javax.annotation.Resource;
import java.math.BigDecimal;

/**
 * 工商銀行實現類,對應的數據庫中的渠道id爲1
 */
@Pay(channelId = 1)
public class ICBCBankImpl implements Strategy {

    @Resource
    private GoodsMapper goodsMapper;

    @Resource
    private ChannelMapper channelMapper;

    /**
     * 根據商品id和銀行渠道id計算優惠後的價格
     *
     * @param goodsId   商品id
     * @param channelId 銀行渠道id
     * @return
     */
    @Override
    public BigDecimal calRecharge(Integer goodsId, Integer channelId) {
        BigDecimal goodsPrice = goodsMapper.getGoodsPriceById(goodsId);
        BigDecimal discountPrice = channelMapper.getDiscountPriceById(channelId);
        if (goodsPrice == null || discountPrice == null) {
            return null;
        }
        return goodsPrice.multiply(discountPrice);
    }
}

 

6.用於標記銀行實現類的註解,定義了一個銀行渠道id屬性:ide

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Pay {
    int channelId();
}

 

7.模擬查詢商品價格的Dao:spa

import java.math.BigDecimal;

public class GoodsMapper {
    public BigDecimal getGoodsPriceById(Integer goodsId) {
        return BigDecimal.valueOf(599);
    }
}

 

8.模擬查詢查詢渠道優惠折扣的Dao:code

import java.math.BigDecimal;

public class ChannelMapper {
    public BigDecimal getDiscountPriceById(Integer channelId) {
        return BigDecimal.valueOf(0.5);
    }
}
相關文章
相關標籤/搜索