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

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

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号