通用计价的简单代码实现

什么场景该使用通用计价

如果商品的费用属性一直在变化,比如隔三岔五的新增某种费用(按新规则计算的新费用),作为开发人员的你每次需要胆战心惊的维护现有的计价接口,测试也需要花费大量时间验证对其他费用的影响。基于这一点,我在想如果初期把计价做成一个通用的计价接口,每次加费用我只需要关注新费用的计算规则,不需要去修改已有费用的规则计算代码,也就可以避免一些BUG的产生。

简单代码实现

总体思路是利用Spring的容器管理,项目启动时将所有计价类型加载在计价执行类中,具体调用方法和平时写代码一样注入就行。这个方法并没有在实际项目中使用。

1. 通用计价接口

import java.math.BigDecimal;
import java.util.Map;

public interface CommonValuation {

    /**
     * 计价类型
     * @return
     */
    String getValuationType();

    /**
     * 计价接口,子类实现自己的计价方式
     * @param paramsJson
     * @param result  保存所有的费用类型及金额
     * @return
     */
    void valuation(String paramsJson, Map<String, BigDecimal> result);

}

说明:这里定义了计价接口,具体的计价类型和计算规则由子类实现,这里会借助Spring来管理子类。

2. 计价接口的执行类


@Component
public class CommonValuationChain {

    @Autowired
    private ApplicationContext applicationContext;

    private List<CommonValuation> commonValuationList = new ArrayList<>();

    /**
     * 加载项目中所有的费用计算类
     */
    @PostConstruct
    private void init() {

        String[]  commonValuationArr = applicationContext.getBeanNamesForType(CommonValuation.class);

        for (String cvName : commonValuationArr) {

            commonValuationList.add(applicationContext.getBean(cvName, CommonValuation.class));
        }

        // 可以通过 @Order 决定计价的顺序
        AnnotationAwareOrderComparator.sort(commonValuationList);

    }

    public Map<String,BigDecimal> valuation(String paramsJson) {
        // 保存所有的费用及对应的金额
        Map<String,BigDecimal> result = new HashMap<>();

        for(CommonValuation valuation : commonValuationList) {
           valuation.valuation(paramsJson, result);
        }

        return result;
    }
}

说明:这里是借助Spring的@PostConstruct注解,将所有的费用类型计算类加载到commonValuationList中,供业务方使用,子类也可以根据@Order注解决定计算的顺序。

3. 具体费用类型


@Component
@Order(4)
public class DiscountMoneyValuation implements CommonValuation{


    /**
     * 减免费
     * @return
     */
    @Override
    public String getValuationType() {
        return "discountMoney";
    }

    @Override
    public void valuation(String paramsJson, Map<String, BigDecimal> result) {
        // 伪代码,这里可以将 paramsJson 转换成需要的计价参数,计算真实价格
        BigDecimal discountMoney = new BigDecimal("-10.6");


        result.put(getValuationType(), discountMoney);
    }
}



@Component
@Order(333)
public class TestMoneyValuation implements CommonValuation{

    @Override
    public String getValuationType() {
        return "testMoney";
    }

    @Override
    public void valuation(String paramsJson, Map<String, BigDecimal> result) {
        // 伪代码,这里可以将 paramsJson 转换成需要的计价参数,计算真实价格
        BigDecimal testMoney = new BigDecimal("100");

        result.put(getValuationType(), testMoney);
    }
}

4. 调用类

	@Autowired
	private CommonValuationChain commonValuationCore;

	@Test
	public void valuationTest() {
        Map<String,BigDecimal> result = commonValuationCore.valuation(null);

		for(Map.Entry<String,BigDecimal> price : result.entrySet()) {
            System.out.println(price.getKey() + ",金额" + price.getValue());
        }
	}

5. 执行结果

总结

以上是我个人对于通用计价的一种实现,本人水平有限,暂时想不到更有扩展性、可用性的方法,如果大家有更好的方法可以在下方评论,同时欢迎大家进行指导和批评。

posted @ 2020-03-24 23:05  yangwqonly  阅读(434)  评论(0编辑  收藏  举报