还在用if else?策略模式了解一下!
在公司负责的就是订单取消业务,老系统中各种类型订单取消都是通过if else 判断不同的订单类型进行不同的逻辑。在经历老系统的折磨和产品需求的不断变更,决定进行一次大的重构:消灭 if else。
接下来就向大家介绍下是如何消灭 if else。
1. if else模式
@Service
public class CancelOrderService {
public void process(OrderDTO orderDTO) {
int serviceType = orderDTO.getServiceType();
if (1 == serviceType) {
System.out.println("取消即时订单");
} else if (2 == serviceType) {
System.out.println("取消预约订单");
} else if (3 == serviceType) {
System.out.println("取消拼车订单");
}
}
}
若干个月再来看就是这样的感觉

2. 策略模式
2.1 策略模式实现的Service
@Service
public class CancelOrderStrategyService {
@Autowired
private StrategyContext context;
public void process(OrderDTO orderDTO) {
OrderTypeEnum orderTypeEnum = OrderTypeEnum.getByCode(orderDTO.getServiceType());
AbstractStrategy strategy = context.getStrategy(orderTypeEnum);
strategy.process(orderDTO);
}
}
简洁的有点过分了是不是!!!
2.2 各种类型策略实现及抽象策略类
下面选取了即时订单和预约订单的策略.
@Service
@OrderTypeAnnotation(orderType = OrderTypeEnum.INSTANT)
public class InstantOrderStrategy extends AbstractStrategy {
@Override
public void process(OrderDTO orderDTO) {
System.out.println("取消即时订单");
}
}
@Service
@OrderTypeAnnotation(orderType = OrderTypeEnum.BOOKING)
public class BookingOrderStrategy extends AbstractStrategy {
@Override
public void process(OrderDTO orderDTO) {
System.out.println("取消预约订单");
}
}
public abstract class AbstractStrategy {
abstract public void process(OrderDTO orderDTO);
}
2.3 策略类型注解
每个策略中增加了注解OrderTypeAnnotation,以标注适用于不同类型的策略内容.
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface OrderTypeAnnotation {
OrderTypeEnum orderType();
}
2.4 策略处理器类StrategyProcessor和策略上下文StrategyContext
其中最为核心的为StrategyProcessor 策略处理器类和StrategyContext 策略上下文,
@Component
public class StrategyProcessor implements BeanFactoryPostProcessor {
private static final String STRATEGY_PACKAGE = "com.lujiahao.strategy";
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
Map<OrderTypeEnum, Class> handlerMap = Maps.newHashMapWithExpectedSize(3);
ClassScanner.scan(STRATEGY_PACKAGE, OrderTypeAnnotation.class).forEach(clazz -> {
OrderTypeEnum type = clazz.getAnnotation(OrderTypeAnnotation.class).orderType();
handlerMap.put(type, clazz);
});
StrategyContext context = new StrategyContext(handlerMap);
configurableListableBeanFactory.registerSingleton(StrategyContext.class.getName(), context);
}
}
public class StrategyContext {
private Map<OrderTypeEnum, Class> strategyMap;
public StrategyContext(Map<OrderTypeEnum, Class> strategyMap) {
this.strategyMap = strategyMap;
}
public AbstractStrategy getStrategy(OrderTypeEnum orderTypeEnum) {
if (orderTypeEnum == null) {
throw new IllegalArgumentException("not fond enum");
}
if (CollectionUtils.isEmpty(strategyMap)) {
throw new IllegalArgumentException("strategy map is empty,please check you strategy package path");
}
Class clazz = strategyMap.get(orderTypeEnum);
if (clazz == null) {
throw new IllegalArgumentException("not fond strategy for type:" + orderTypeEnum.getCode());
}
return (AbstractStrategy) SpringBeanUtils.getBean(clazz);
}
}
- 首先会扫描指定包中标有@OrderTypeAnnotation的类
- 将符合类的对应的枚举值作为key,对应的类作为value,保存在策略Map中
- 初始化StrategyContext,并注册到spring容器中,同时将策略Map传入其中
我们使用了枚举作为Map中的key,相信大家很少有人这样操作过,不过可以放心操作.通过下面两篇文章解答大家的疑问.
3. 总结
策略模式极大的减少if else等模板代码,在提升代码可读性的同时,也大大增加代码的灵活性,添加新的策略即可以满足业务需求.
本人在我司业务中对策略模式的应用得到了很好的验证,从此再也不用担心产品改需求.
用策略模式一时爽,一直用一直爽
还在用if else?策略模式了解一下!的更多相关文章
- 策略模式(Strategy Pattern)
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. 环境类(Context):用一个ConcreteStrategy对象来配置. ...
- Java设计模式之-----策略模式
首先,我们来看下策略模式的概念.一般的解释如下: 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化.(原文:The St ...
- 设计模式学习——策略模式(Strategy Pattern)
0. 前言 最近在重构公司的一个项目的时候,在抽取DES加密重复部分代码的时候,突然间想起了策略模式,感觉策略模式好像可以应用上,于是重新学习了下策略模式.注:在DES加密中,有DES和TDES算法, ...
- [工作中的设计模式]策略模式stategy
一.模式解析 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. 策略模式的关键点为: 1.多种算法存在 2.算法继承同样的接口 ...
- head first 设计模式读书笔记 之 策略模式
作为一个php开发者,深知曾经很多程序员都鄙视php,为什么呢?因为他们认为php的语法是dirty的,并且由于开发者水平参差不齐导致php的代码更加乱上加乱,维护起来简直一坨shit一样.随着php ...
- 策略模式Strategy——坐什么车回家?
1.存在的问题和模型 :2014年6月 学校:廊坊师范 家:石家庄 人物:学生 又快到期末考试了.回家的节奏也奔上日程,无聊之余就想想这次回家的事儿. 对我来说回 ...
- 第21章 策略模式(Strategy Pattern)
原文 第21章 策略模式(Strategy Pattern) 策略模式 导读:策略模式看完之后,大多数人都会感觉有点混了,包括我,感觉策略模式是一种OO思想的体现(纯属个人拙见). 概述: ...
- headfirst设计模式(1)—策略模式
什么是策略模式 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化(摘自百度百科) 关键字:算法封装,相互替换,独立变化 算法封装 ...
- [.net 面向对象程序设计深入](24)实战设计模式——策略模式(行为型)
[.net 面向对象程序设计深入](24)实战设计模式——策略模式(行为型) 1,策略模式定义 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它 ...
- OOAD之策略模式(1)
在引入策略模式之前.先用一个小项目解释为什么要有策略模式.这是一个模拟鸭子的小游戏.最开始需求为,所有的鸭子都会叫以及都会游泳且叫声游泳姿势都一样.因此我们用原始OO的思维去编写代码时很容易做到 pu ...
随机推荐
- 最全面阐述WebDataBinder理解Spring的数据绑定
每篇一句 不要总问低级的问题,这样的人要么懒,不愿意上网搜索,要么笨,一点独立思考的能力都没有 相关阅读 [小家Spring]聊聊Spring中的数据绑定 --- DataBinder本尊(源码分析) ...
- 嵌入式web服务器BOA的移植及应用
嵌入式web服务器子系统 一.嵌入式web服务器的控制流程 如下图所示,嵌入式web服务器可实现通过网络远程控制嵌入式开发板,便捷实用. 控制流程:浏览器 --->>>嵌入式开发板 ...
- MyBatis一对多和多对多xml配置
MyBatis一对多和多对多xml配置 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ma ...
- Linux基础学习整理
linux学习记录 下载地址 centos 下载地址: 网易镜像:http://mirrors.163.com/centos/6/isos/ 搜狐镜像:http://mirrors.sohu.com/ ...
- Linux系统安装Tomcat——.tar.gz版
1.rpm.deb.tar.gz的区别: rpm格式的软件包适用于基于Red Hat发行版的系统,例如Red Hat Linux.SUSE.Fedora. deb格式的软件包则是适用于基于Debian ...
- kaptcha谷歌验证码工具
Kaptcha 简介 Kaptcha 是一个可高度配置的实用验证码生成工具,可自由配置的选项如: 验证码的字体 验证码字体的大小 验证码字体的字体颜色 验证码内容的范围(数字,字母,中文汉字!) 验证 ...
- java - java集合类
1.接口实现类 ①List List list1 = new ArrayList(); List list2 = new LinkedList(); ②Set Set<String> se ...
- MyBatis Generator Example.Criteria 查询条件复制
背景: 我们在开发中使用MyBatis Generator生成的 XxxExample查询时,咋添加 or 查询时候,可能两个 Example.Criteria 对象的条件存在交集,即多个查询条件是相 ...
- LinkedList实现类
List还有一个LinkedList的实现,它是一个基于链表实现的List类,对于顺序访问集合中的元素进行了优化,特别是当插入.删除元素时速度非常快.因为LinkedList即实现了List接口,也实 ...
- Redis(六)--- Redis过期策略与内存淘汰机制
1.简述 关于Redis键的过期策略,首先要了解两种时间的区别,生存时间和过期时间: 生存时间:一段时长,如30秒.6000毫秒,设置键的生存时间就是设置这个键可以存在多长时间,命令有两个 expir ...