在公司负责的就是订单取消业务,老系统中各种类型订单取消都是通过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?策略模式了解一下!的更多相关文章

  1. 策略模式(Strategy Pattern)

    策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. 环境类(Context):用一个ConcreteStrategy对象来配置. ...

  2. Java设计模式之-----策略模式

    首先,我们来看下策略模式的概念.一般的解释如下:     策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化.(原文:The St ...

  3. 设计模式学习——策略模式(Strategy Pattern)

    0. 前言 最近在重构公司的一个项目的时候,在抽取DES加密重复部分代码的时候,突然间想起了策略模式,感觉策略模式好像可以应用上,于是重新学习了下策略模式.注:在DES加密中,有DES和TDES算法, ...

  4. [工作中的设计模式]策略模式stategy

    一.模式解析 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. 策略模式的关键点为: 1.多种算法存在 2.算法继承同样的接口 ...

  5. head first 设计模式读书笔记 之 策略模式

    作为一个php开发者,深知曾经很多程序员都鄙视php,为什么呢?因为他们认为php的语法是dirty的,并且由于开发者水平参差不齐导致php的代码更加乱上加乱,维护起来简直一坨shit一样.随着php ...

  6. 策略模式Strategy——坐什么车回家?

    1.存在的问题和模型 :2014年6月       学校:廊坊师范        家:石家庄       人物:学生 又快到期末考试了.回家的节奏也奔上日程,无聊之余就想想这次回家的事儿. 对我来说回 ...

  7. 第21章 策略模式(Strategy Pattern)

    原文 第21章 策略模式(Strategy Pattern) 策略模式 导读:策略模式看完之后,大多数人都会感觉有点混了,包括我,感觉策略模式是一种OO思想的体现(纯属个人拙见). 概述:       ...

  8. headfirst设计模式(1)—策略模式

    什么是策略模式 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化(摘自百度百科) 关键字:算法封装,相互替换,独立变化 算法封装 ...

  9. [.net 面向对象程序设计深入](24)实战设计模式——策略模式(行为型)

    [.net 面向对象程序设计深入](24)实战设计模式——策略模式(行为型) 1,策略模式定义 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它 ...

  10. OOAD之策略模式(1)

    在引入策略模式之前.先用一个小项目解释为什么要有策略模式.这是一个模拟鸭子的小游戏.最开始需求为,所有的鸭子都会叫以及都会游泳且叫声游泳姿势都一样.因此我们用原始OO的思维去编写代码时很容易做到 pu ...

随机推荐

  1. MyBatis从入门到精通:第一章的pom.xml文件

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...

  2. linux svn 中文 https://my.oschina.net/VASKS/blog/659236

    https://my.oschina.net/VASKS/blog/659236 设置服务器: export LC_ALL=zh_CN.UTF-8长久之计, echo export LC_ALL=zh ...

  3. 《VR入门系列教程》之17---发布第一个应用

    发布运行     Unity可以支持多种目标平台的发布,包括:桌面端.Web端.移动端.游戏主机端.     发布运行之前的Cubes场景至桌面端,我们先选择File->Build Settin ...

  4. TP框架基础(一)

    [使用框架]  官网:thinkphp.cn.  目前建议使用thinkPHP3.2版本 一.结构目录>Thinkphp文件夹,是thinkPHP的核心文件,里面的内容是不允许我们修改的 > ...

  5. 解读equals()和hashCode()

    前面部分摘自:https://blog.csdn.net/javazejian/article/details/51348320 一:Object中equals方法的实现原理 public boole ...

  6. linux初学者-延迟及定时任务篇

    linux初学者-延迟及定时任务篇 在linux系统的学习工作中,南面会遇到需要延迟进行的任务和需要定时去完成的任务,就像手机的闹钟一样,这时候就需要用到linux系统当中的系统延迟和定时任务的设置了 ...

  7. 数据结构与算法基础之malloc()动态分配内存概述

    动态内存分配和释放: 动态构造一维数组: 假设动态构造一个Int型数组: int *p = (int *)malloc(int len); //还可以写作: int *p = (int *)mallo ...

  8. 林大妈的JavaScript基础知识(二):编写JavaScript代码前的一些简单工作

    在介绍JavaScript语法前,我们需要知道,学习语法必须要多利用手敲代码来巩固记忆.因此,由于JavaScript的特性,它不能像C++和Java一样独立地编译及运行,我们需要在调试运行JavaS ...

  9. TestNG在Eclipse中运行的几种方法

    目录 1 在Eclipse Outline视图中,点右键run as TestNG Test (不推荐) 2 在Eclipse类编辑界面,直接点击右键run as TestNG Test 3 通过Te ...

  10. Lombok 使用介绍(常见注解)

    目录 @Data @NonNull @Getter & @Setter @ToString @EqualsAndHashCode @NoArgsConstructor, @RequiredAr ...