zoukankan      html  css  js  c++  java
  • 在商城系统中使用设计模式----策略模式之在spring中使用策略模式

    1.前言:

     这是策略模式在spring中的使用,对策略模式不了解对同学可以移步在商城中简单对使用策略模式

    2.问题:

    在策略模式中,我们创建表示各种策略的对象和一个行为,随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

    在spring 中,策略对象在正常情况下是,在启动Spring容器对时候,已经将策略对象加载创建完成成为bean。

    我们如何在Spring中正确对使用策略模式,这样又会发生什么问题呢?

    3.使用场景: 

      场景:商城活动中有几种,满减,打折,送积分.我们要获取商品对最终价格。

    4.实现

    步骤一.创建接口类 

    public interface GoodsActivity {
    
        /**
         * 获取应该支付的金额
         * @param amount 商品的单价
         * @return
         */
        BigDecimal getPayPrice(BigDecimal amount);
    
    }

     步骤二.实现接口,并添加@Component注解

    @Component
    public class DiscountActivity implements GoodsActivity {
    
        //折扣
        private double discount ;
    
        @Override
        public BigDecimal getPayPrice(BigDecimal amount) {
    
            //假装从数据库的配置表取折扣
            discount = 8.0;
    
            return new BigDecimal(discount).multiply(amount).divide(new BigDecimal(10));
        }
    }
    @Component
    public class FullReduceActivity implements GoodsActivity {
    
        //满多少
        private BigDecimal fullAmount;
    
        //减多少
        private BigDecimal reductionAmount ;
    
        @Override
        public BigDecimal getPayPrice(BigDecimal amount) {
    
            //假装从数据库的配置表取配置数据
            fullAmount = new BigDecimal(300);
    
            reductionAmount  = new BigDecimal(100);
    
            return amount.compareTo(fullAmount)>=0?amount.subtract(reductionAmount):amount;
        }
    }
    @Component
    public class IntegralActivity implements GoodsActivity {
    
        //抵扣的积分  10积分=1元
        private int integral = 100;
    
        @Override
        public BigDecimal getPayPrice(BigDecimal amount) {
            return amount.subtract(new BigDecimal(integral/10));
        }
    }

    步骤三.创建context

    public class GoodsActivityContext {
    
        private GoodsActivity goodsActivity;
    
        public GoodsActivityContext(GoodsActivity goodsActivity){
            this.goodsActivity=goodsActivity;
        }
    
        /**
         * 获取商品价格
         * @param amount
         * @return
         */
        public BigDecimal getPrice(BigDecimal amount){
            return goodsActivity.getPayPrice(amount);
        }
    
    }

    步骤四.在控制层中调用策略模式

    @RestController
    public class ActivityController{
    
        @Autowired
        private DiscountActivity discountActivity;
    
        @Autowired
        private FullReduceActivity fullReduceActivity;
    
        @Autowired
        private IntegralActivity integralActivity;
    
    
        /**
         * 获取最终售价
         *  (这样的控制层写法很不友好,需要写大量的代码去实现)
         *      为了解决这个问题,将引用工厂模式...
         *
         *      工厂是创建型模式,它的作用就是创建对象;
         *      策略是行为型模式,它的作用是让一个对象在许多行为中选择一种行为;
         *
         *  解决不同的问题
         * 工厂模式是创建型的设计模式,它接受指令,创建出符合要求的实例;它主要解决的是资源的统一分发,将对象的创建完全独立出来,让对象的创建和具体的使用客户无关。主要应用在多数据库选择,类库文件加载等。
         * 策略模式是为了解决的是策略的切换与扩展,更简洁的说是定义策略族,分别封装起来,让他们之间可以相互替换,策略模式让策略的变化独立于使用策略的客户。
         *
         * 工厂相当于黑盒子,策略相当于白盒子;
         *
         *
         * @param activityType
         * @param amount
         * @return
         */
        @RequestMapping("getLastPrice")
        public ResponseResult getLastPrice(String activityType,BigDecimal amount){
    
            ResponseResult responseResult = ResponseResult.getInstance();
    
            GoodsActivityContext goodsActivityContext;
    
            //根据活动类型获取最终售价
            switch (activityType){
                case "discount":
                    goodsActivityContext = new GoodsActivityContext(discountActivity);
                    break;
                case "fullReduce":
                    goodsActivityContext = new GoodsActivityContext(fullReduceActivity);
                    break;
                case "integral":
                    goodsActivityContext = new GoodsActivityContext(integralActivity);
                    break;
                default:
                    responseResult.setCode(1);
                    responseResult.setMsg("数据类型错误");
                    responseResult.setData(null);
                    return responseResult;
            }
    
            responseResult.setCode(0);
            responseResult.setMsg("操作成功");
            responseResult.setData(goodsActivityContext.getPrice(amount));
    
            return responseResult;
        }
    
    
    }

    总结:按照注释说明,很明显我们需要优化这个策略模式。

     步骤三:(2) 引入工厂模式,对策略对象进行管理

    @Component
    public class GoodsActivityStrategyFactory {
    
        @Autowired
        private Map<String,GoodsActivity> goodsActivityMap;
    
        /**
         * 根据活动类型 获取所对应的策略
         * @param activityType
         */
        public GoodsActivityContext getGoodsActivityStrategy(String activityType){
    
            GoodsActivityContext goodsActivityContext;
    
            switch (activityType){
                case "discount":
                    goodsActivityContext = new GoodsActivityContext(goodsActivityMap.get("discountActivity"));
                    break;
                case "fullReduce":
                    goodsActivityContext = new GoodsActivityContext(goodsActivityMap.get("fullReduceActivity"));
                    break;
                case "integral":
                    goodsActivityContext = new GoodsActivityContext(goodsActivityMap.get("integralActivity"));
                    break;
                default:
                    goodsActivityContext = null;
            }
    
            return goodsActivityContext;
        }
    
    }

    步骤四.在控制层中调用策略模式

    @RestController
    public class ActivityController{
    
        @Autowired
        private GoodsActivityStrategyFactory goodsActivityStrategyFactory;
    
    
        @RequestMapping("getLastPrice_V2")
        public ResponseResult getLastPrice_V2(String activityType,BigDecimal amount){
    
    
            ResponseResult responseResult = ResponseResult.getInstance();
            //从工厂中获取  活动策略
            GoodsActivityContext goodsActivityContext = goodsActivityStrategyFactory.getGoodsActivityStrategy(activityType);
    
            if (goodsActivityContext==null){
                responseResult.setCode(1);
                responseResult.setData(null);
                responseResult.setMsg("数据类型错误");
                return responseResult;
            }
    
            responseResult.setCode(0);
            responseResult.setMsg("操作成功");
            responseResult.setData(goodsActivityContext.getPrice(amount));
    
            return responseResult;
    
        }
    }

    源码:

    在springboot中使用策略模式

     

     在工作中,不能灵活的时候设计模式。希望通过这次的学习,可以加深对设计模式对理解。

    接下来会继续整理出自己在工作对时候可以使用对设计模式,不对望指点。如果文章对您有帮助,github给个start吧。

  • 相关阅读:
    9.17 HTML CSS
    9.16
    9.15
    9.14
    9.13
    9.12
    9.11
    9.10
    9.9
    9.8
  • 原文地址:https://www.cnblogs.com/boychen/p/10721078.html
Copyright © 2011-2022 走看看