在商城系统中使用设计模式----策略模式之在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;
- }
- }
源码:
在工作中,不能灵活的时候设计模式。希望通过这次的学习,可以加深对设计模式对理解。
接下来会继续整理出自己在工作对时候可以使用对设计模式,不对望指点。如果文章对您有帮助,github给个start吧。
在商城系统中使用设计模式----策略模式之在spring中使用策略模式的更多相关文章
- 设计模式_策略模式_在Spring中的应用
一.理论 在spring中经常有读取配置文件的需求,这里就会用到一个Spring提供的Resource接口 Resource 接口是具体资源访问策略的抽象,也是所有资源访问类所实现的接口.Resour ...
- ssh下:系统初始化实现ServletContextListener接口时,获取spring中数据层对象无效的问题
想要实现的功能:SSH环境下,数据层都交由Spring管理:在服务启动时,将数据库中的一些数据加载到ServletContext中缓存起来. 系统初始化类需要实现两个接口: ServletContex ...
- spring中bean的五种作用域?Spring中的bean是线程安全的吗?
spring中bean的五种作用域 当通过spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域.Spring支持如下5种作用域: singleto ...
- Spring中单例模式中的饿汉和懒汉以及Spring中的多例模式
链接:https://pan.baidu.com/s/1wgxnXnGbPdK1YaZvhO7PDQ 提取码:opjr 单例模式:每个bean定义只生成一个对象实例,每次getBean请求获得的都是此 ...
- 访何红辉:谈谈Android源码中的设计模式
最近Android 6.0版本的源代码开放下载,刚好分析Android源码的技术书籍<Android源码设计模式解析与实战>上市,我们邀请到它的作者何红辉,来谈谈Android源码中的设计 ...
- (转)Spring中Singleton模式的线程安全
不知道哪里的文章,总结性还是比较好的.但是代码凌乱,有的还没有图.如果找到原文了可以进行替换! spring中的单例 spring中管理的bean实例默认情况下是单例的[sigleton类型],就还有 ...
- spring 中常用的设计模式
一. Spring 中常见的设计模式 工厂模式 : BeanFactory 装饰器模式: BeanWrapper 代理模式: AopProxy 单例模式: ApplicationContext 委派模 ...
- Spring 中使用了那些设计模式呢?
一. Spring 中常见的设计模式 工厂模式 : BeanFactory 装饰器模式: BeanWrapper 代理模式: AopProxy 单例模式: ApplicationContext 委派模 ...
- Tomcat 系统架构与设计模式
Tomcat 系统架构与设计模式,第 1 部分: 工作原理 这个分为两个部分的系列文章将研究 Apache Tomcat 的系统架构以及其运用的很多经典设计模式.本文是第 1 部分,将主要从 Tomc ...
随机推荐
- UML(一)下载与安装
三步 Step1 下载绿色版: http://www.pc6.com/softview/SoftView_64080.html Step2 下载汉化包,(提供一个地址): http://downloa ...
- Java用户界面技术
组件 文本框.复选框.下拉框.文本区域框.列表listbox.按钮.文本标签 布局 layout属性们.panel java.swing包 JButton JL ...
- C#-委派和事件
委派代表一个方法.当不知道后面的方法名称时,可用委派先声明,待使用方法时,再在委派实例化时写入方法名称. 先声明, public delegate int delegateClassName (参数列 ...
- android Activity中设置setResult 没有触发onActivityResult
昨天修改<manifest 文件中activity 的 模式为单例模式:android:launchMode="singleTask" ,发现我的onActivityResu ...
- npm 及安装
一.npm nodejs使开发者摆脱了浏览器的束缚,一系列基于nodejs的应用和工具不断出现,无论是在node应用的开发,还是使用中,包管理都扮演着一个很重要的作用.NPM(node package ...
- POJ 2570 线段树
Potted Flower Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Jav ...
- Sql递归关联情况,With作为开头条件。
with Test_Recursion(Id,ParentId)AS(select Id,ParentId from [V_KPI_DetailsActivities] where ParentId ...
- RGB-D数据集(SLAM的和行人检测的)
移动机器人编程一般用mrpt,这个软件来做三维,里面封装了很多常用算法. http://www.mrpt.org/download-mrpt/ SLAM的数据集,其中包括机器人slam http:// ...
- 在线安装WordPress更新 失败的解决办法
1. 登录ftp登录不上 , 总是登录失败 在服务器上新建了一个vsftpd服务器,并设置了相应的虚拟用户,修改chroot到网站目录 相关连接:https://blog.csdn.net/zhan ...
- Download SQL Server Management Studio (SSMS)下载地址
Download SQL Server Management Studio (SSMS)下载地址: https://msdn.microsoft.com/en-us/library/mt238290. ...