1.前言:

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

2.问题:

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

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

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

3.使用场景: 

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

4.实现

步骤一.创建接口类

  1. public interface GoodsActivity {
  2.  
  3. /**
  4. * 获取应该支付的金额
  5. * @param amount 商品的单价
  6. * @return
  7. */
  8. BigDecimal getPayPrice(BigDecimal amount);
  9.  
  10. }

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

  1. @Component
  2. public class DiscountActivity implements GoodsActivity {
  3.  
  4. //折扣
  5. private double discount ;
  6.  
  7. @Override
  8. public BigDecimal getPayPrice(BigDecimal amount) {
  9.  
  10. //假装从数据库的配置表取折扣
  11. discount = 8.0;
  12.  
  13. return new BigDecimal(discount).multiply(amount).divide(new BigDecimal(10));
  14. }
  15. }
  1. @Component
  2. public class FullReduceActivity implements GoodsActivity {
  3.  
  4. //满多少
  5. private BigDecimal fullAmount;
  6.  
  7. //减多少
  8. private BigDecimal reductionAmount ;
  9.  
  10. @Override
  11. public BigDecimal getPayPrice(BigDecimal amount) {
  12.  
  13. //假装从数据库的配置表取配置数据
  14. fullAmount = new BigDecimal(300);
  15.  
  16. reductionAmount = new BigDecimal(100);
  17.  
  18. return amount.compareTo(fullAmount)>=0?amount.subtract(reductionAmount):amount;
  19. }
  20. }
  1. @Component
  2. public class IntegralActivity implements GoodsActivity {
  3.  
  4. //抵扣的积分 10积分=1元
  5. private int integral = 100;
  6.  
  7. @Override
  8. public BigDecimal getPayPrice(BigDecimal amount) {
  9. return amount.subtract(new BigDecimal(integral/10));
  10. }
  11. }

步骤三.创建context

  1. public class GoodsActivityContext {
  2.  
  3. private GoodsActivity goodsActivity;
  4.  
  5. public GoodsActivityContext(GoodsActivity goodsActivity){
  6. this.goodsActivity=goodsActivity;
  7. }
  8.  
  9. /**
  10. * 获取商品价格
  11. * @param amount
  12. * @return
  13. */
  14. public BigDecimal getPrice(BigDecimal amount){
  15. return goodsActivity.getPayPrice(amount);
  16. }
  17.  
  18. }

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

  1. @RestController
  2. public class ActivityController{
  3.  
  4. @Autowired
  5. private DiscountActivity discountActivity;
  6.  
  7. @Autowired
  8. private FullReduceActivity fullReduceActivity;
  9.  
  10. @Autowired
  11. private IntegralActivity integralActivity;
  12.  
  13. /**
  14. * 获取最终售价
  15. * (这样的控制层写法很不友好,需要写大量的代码去实现)
  16. * 为了解决这个问题,将引用工厂模式...
  17. *
  18. * 工厂是创建型模式,它的作用就是创建对象;
  19. * 策略是行为型模式,它的作用是让一个对象在许多行为中选择一种行为;
  20. *
  21. * 解决不同的问题
  22. * 工厂模式是创建型的设计模式,它接受指令,创建出符合要求的实例;它主要解决的是资源的统一分发,将对象的创建完全独立出来,让对象的创建和具体的使用客户无关。主要应用在多数据库选择,类库文件加载等。
  23. * 策略模式是为了解决的是策略的切换与扩展,更简洁的说是定义策略族,分别封装起来,让他们之间可以相互替换,策略模式让策略的变化独立于使用策略的客户。
  24. *
  25. * 工厂相当于黑盒子,策略相当于白盒子;
  26. *
  27. *
  28. * @param activityType
  29. * @param amount
  30. * @return
  31. */
  32. @RequestMapping("getLastPrice")
  33. public ResponseResult getLastPrice(String activityType,BigDecimal amount){
  34.  
  35. ResponseResult responseResult = ResponseResult.getInstance();
  36.  
  37. GoodsActivityContext goodsActivityContext;
  38.  
  39. //根据活动类型获取最终售价
  40. switch (activityType){
  41. case "discount":
  42. goodsActivityContext = new GoodsActivityContext(discountActivity);
  43. break;
  44. case "fullReduce":
  45. goodsActivityContext = new GoodsActivityContext(fullReduceActivity);
  46. break;
  47. case "integral":
  48. goodsActivityContext = new GoodsActivityContext(integralActivity);
  49. break;
  50. default:
  51. responseResult.setCode(1);
  52. responseResult.setMsg("数据类型错误");
  53. responseResult.setData(null);
  54. return responseResult;
  55. }
  56.  
  57. responseResult.setCode(0);
  58. responseResult.setMsg("操作成功");
  59. responseResult.setData(goodsActivityContext.getPrice(amount));
  60.  
  61. return responseResult;
  62. }
  63.  
  64. }

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

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

  1. @Component
  2. public class GoodsActivityStrategyFactory {
  3.  
  4. @Autowired
  5. private Map<String,GoodsActivity> goodsActivityMap;
  6.  
  7. /**
  8. * 根据活动类型 获取所对应的策略
  9. * @param activityType
  10. */
  11. public GoodsActivityContext getGoodsActivityStrategy(String activityType){
  12.  
  13. GoodsActivityContext goodsActivityContext;
  14.  
  15. switch (activityType){
  16. case "discount":
  17. goodsActivityContext = new GoodsActivityContext(goodsActivityMap.get("discountActivity"));
  18. break;
  19. case "fullReduce":
  20. goodsActivityContext = new GoodsActivityContext(goodsActivityMap.get("fullReduceActivity"));
  21. break;
  22. case "integral":
  23. goodsActivityContext = new GoodsActivityContext(goodsActivityMap.get("integralActivity"));
  24. break;
  25. default:
  26. goodsActivityContext = null;
  27. }
  28.  
  29. return goodsActivityContext;
  30. }
  31.  
  32. }

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

  1. @RestController
  2. public class ActivityController{
  3.  
  4. @Autowired
  5. private GoodsActivityStrategyFactory goodsActivityStrategyFactory;
  6.  
  7. @RequestMapping("getLastPrice_V2")
  8. public ResponseResult getLastPrice_V2(String activityType,BigDecimal amount){
  9.  
  10. ResponseResult responseResult = ResponseResult.getInstance();
  11. //从工厂中获取 活动策略
  12. GoodsActivityContext goodsActivityContext = goodsActivityStrategyFactory.getGoodsActivityStrategy(activityType);
  13.  
  14. if (goodsActivityContext==null){
  15. responseResult.setCode(1);
  16. responseResult.setData(null);
  17. responseResult.setMsg("数据类型错误");
  18. return responseResult;
  19. }
  20.  
  21. responseResult.setCode(0);
  22. responseResult.setMsg("操作成功");
  23. responseResult.setData(goodsActivityContext.getPrice(amount));
  24.  
  25. return responseResult;
  26.  
  27. }
  28. }

源码:

在springboot中使用策略模式

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

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

在商城系统中使用设计模式----策略模式之在spring中使用策略模式的更多相关文章

  1. 设计模式_策略模式_在Spring中的应用

    一.理论 在spring中经常有读取配置文件的需求,这里就会用到一个Spring提供的Resource接口 Resource 接口是具体资源访问策略的抽象,也是所有资源访问类所实现的接口.Resour ...

  2. ssh下:系统初始化实现ServletContextListener接口时,获取spring中数据层对象无效的问题

    想要实现的功能:SSH环境下,数据层都交由Spring管理:在服务启动时,将数据库中的一些数据加载到ServletContext中缓存起来. 系统初始化类需要实现两个接口: ServletContex ...

  3. spring中bean的五种作用域?Spring中的bean是线程安全的吗?

    spring中bean的五种作用域 当通过spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域.Spring支持如下5种作用域: singleto ...

  4. Spring中单例模式中的饿汉和懒汉以及Spring中的多例模式

    链接:https://pan.baidu.com/s/1wgxnXnGbPdK1YaZvhO7PDQ 提取码:opjr 单例模式:每个bean定义只生成一个对象实例,每次getBean请求获得的都是此 ...

  5. 访何红辉:谈谈Android源码中的设计模式

    最近Android 6.0版本的源代码开放下载,刚好分析Android源码的技术书籍<Android源码设计模式解析与实战>上市,我们邀请到它的作者何红辉,来谈谈Android源码中的设计 ...

  6. (转)Spring中Singleton模式的线程安全

    不知道哪里的文章,总结性还是比较好的.但是代码凌乱,有的还没有图.如果找到原文了可以进行替换! spring中的单例 spring中管理的bean实例默认情况下是单例的[sigleton类型],就还有 ...

  7. spring 中常用的设计模式

    一. Spring 中常见的设计模式 工厂模式 : BeanFactory 装饰器模式: BeanWrapper 代理模式: AopProxy 单例模式: ApplicationContext 委派模 ...

  8. Spring 中使用了那些设计模式呢?

    一. Spring 中常见的设计模式 工厂模式 : BeanFactory 装饰器模式: BeanWrapper 代理模式: AopProxy 单例模式: ApplicationContext 委派模 ...

  9. Tomcat 系统架构与设计模式

    Tomcat 系统架构与设计模式,第 1 部分: 工作原理 这个分为两个部分的系列文章将研究 Apache Tomcat 的系统架构以及其运用的很多经典设计模式.本文是第 1 部分,将主要从 Tomc ...

随机推荐

  1. UML(一)下载与安装

    三步 Step1 下载绿色版: http://www.pc6.com/softview/SoftView_64080.html Step2 下载汉化包,(提供一个地址): http://downloa ...

  2. Java用户界面技术

    组件     文本框.复选框.下拉框.文本区域框.列表listbox.按钮.文本标签   布局     layout属性们.panel   java.swing包     JButton     JL ...

  3. C#-委派和事件

    委派代表一个方法.当不知道后面的方法名称时,可用委派先声明,待使用方法时,再在委派实例化时写入方法名称. 先声明, public delegate int delegateClassName (参数列 ...

  4. android Activity中设置setResult 没有触发onActivityResult

    昨天修改<manifest 文件中activity 的 模式为单例模式:android:launchMode="singleTask" ,发现我的onActivityResu ...

  5. npm 及安装

    一.npm nodejs使开发者摆脱了浏览器的束缚,一系列基于nodejs的应用和工具不断出现,无论是在node应用的开发,还是使用中,包管理都扮演着一个很重要的作用.NPM(node package ...

  6. POJ 2570 线段树

    Potted Flower Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Jav ...

  7. Sql递归关联情况,With作为开头条件。

    with Test_Recursion(Id,ParentId)AS(select Id,ParentId  from [V_KPI_DetailsActivities] where ParentId ...

  8. RGB-D数据集(SLAM的和行人检测的)

    移动机器人编程一般用mrpt,这个软件来做三维,里面封装了很多常用算法. http://www.mrpt.org/download-mrpt/ SLAM的数据集,其中包括机器人slam http:// ...

  9. 在线安装WordPress更新 失败的解决办法

    1.  登录ftp登录不上 , 总是登录失败 在服务器上新建了一个vsftpd服务器,并设置了相应的虚拟用户,修改chroot到网站目录 相关连接:https://blog.csdn.net/zhan ...

  10. Download SQL Server Management Studio (SSMS)下载地址

    Download SQL Server Management Studio (SSMS)下载地址: https://msdn.microsoft.com/en-us/library/mt238290. ...