来自 技术 2019-04-17 00:00 的文章

在商城系统中使用设计模式----策略模式之在spr

1.前言:

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

2.问题:

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

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

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

3.使用场景: 

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

4.实现

步骤一.创建接口类

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

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

@Componentpublic 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)); }}

@Componentpublic 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; }}

@Componentpublic 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); }}

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

@RestControllerpublic 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) 引入工厂模式,对策略对象进行管理

@Componentpublic 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; }}

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

@RestControllerpublic 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吧。