zoukankan      html  css  js  c++  java
  • 如何将业务代码写得像诗一样(使用注解+单例+工厂去掉一大波if和else判断)

    1.订单控制器,提供一个根据商品id和银行渠道id计算商品折后价格的接口:

    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.上下文:

    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反射获取对应银行具体的实现类:

    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:

    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属性:

    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:

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

    8.模拟查询查询渠道优惠折扣的Dao:

    import java.math.BigDecimal;
    
    public class ChannelMapper {
        public BigDecimal getDiscountPriceById(Integer channelId) {
            return BigDecimal.valueOf(0.5);
        }
    }
  • 相关阅读:
    【Prince2科普】Prince2七大主题之概论
    浅谈PRINCE2和PMP体系架构有何区别?
    Prince2是怎么考试的?
    Reporting Service服务SharePoint集成模式安装配置(3、4、安装sharepoint 2010必备组件及产品)
    Reporting Service服务SharePoint集成模式安装配置(1、虚拟机+ 2、AD域环境配置)
    DB2 添加license
    db2中临时表在存储过程中的使用
    DB2 函数快速构造测试数据
    db2 中 SQL判断物理表是否存在、修改表名
    DB2触发器简单例子
  • 原文地址:https://www.cnblogs.com/jun1019/p/11795515.html
Copyright © 2011-2022 走看看