前段时间,我将公司系统中的批量审单的功能进行了重构,用到了java的并发编程进行异步化处理,数据库的乐观锁机制处理多线程并发更新数据。其中批量审单的业务处理涉及到多种任务类型,对应不同的业务方法进行处理,比如转仓,转快递,添加赠品,删除赠品,拆分订单,批量驳回,批量作废等等,其中就用到了策略模式。

if else模式

        if ("BATCH_CHANGE_WAREHOUSE".equals(taskType)) {//批量转仓逻辑} else if ("BATCH_CHANGE_SHIPPING".equals(taskType)) {//批量转快递逻辑} else if ("BATCH_REPLACE_ORDER_GOODS".equals(taskType)) {//批量替换订单商品逻辑} else if ("BATCH_DELETE_ORDER_GOODS".equals(taskType)) {//批量删除订单商品逻辑} else if ("BATCH_ADD_MEMO".equals(taskType)) {//批量添加备注逻辑} else {//任务类型未知System.out.println("任务类型无法处理");}

看起来,思路清晰,if,else分支也很清楚,但不觉得代码很臃肿,维护起来麻烦吗,尤其是其他人来接锅的时候,连看下去的欲望都没有了。这时候你需要用策略模式消除其中的if else,进行一下简单的重构!

策略模式

1、首先抽象业务处理器

public abstract class InspectionSolver {public abstract void solve(Long orderId, Long userId);public abstract String[] supports();
}

2、将业务处理器和其支持处理的类型放到一个容器中,java里Map就是最常用的容器之一

@Component
public class InspectionSolverChooser implements ApplicationContextAware{private Map<String, InspectionSolver> chooseMap = new HashMap<>();public InspectionSolver choose(String type) {return chooseMap.get(type);}@PostConstructpublic void register() {Map<String, InspectionSolver> solverMap = context.getBeansOfType(InspectionSolver.class);for (InspectionSolver solver : solverMap.values()) {for (String support : solver.supports()) {chooseMap.put(support,solver);}}}private ApplicationContext context;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.context=applicationContext;}
}

这里是在应用启动的时候,加载spring容器中所有InspectionSolver类型的处理器,放到InspectionSolverChooser的map容器中。注意是InspectionSolver类型,所以定义的处理器都得继承InspectionSolver,其次是spring容器中的才能加载,所以定义的处理器都得放到spring容器中(@Component注解不能少)

3、定义不同的处理器

@Component
public class ChangeWarehouseSolver extends InspectionSolver {@Overridepublic void solve(Long orderId, Long userId) {System.out.println("订单"+orderId+"开始进行批量转仓了。。");}@Overridepublic String[] supports() {return new String[] {InspectionConstant.INSPECTION_TASK_TYPE_BATCH_CHANGE_WAREHOUSE};}
}@Component
public class ChangeShippingSolver extends InspectionSolver{@Overridepublic void solve(Long orderId, Long userId) {System.out.println("订单"+orderId+"开始进行转快递了。。");}@Overridepublic String[] supports() {return new String[] {InspectionConstant.INSPECTION_TASK_TYPE_BATCH_CHANGE_SHIPPING};}
}@Component
public class ReplaceOrderGoodsSolver extends InspectionSolver{@Overridepublic void solve(Long orderId, Long userId) {System.out.println("订单"+orderId+"开始进行替换商品了");}@Overridepublic String[] supports() {return new String[]{InspectionConstant.INSPECTION_TASK_TYPE_BATCH_REPLACE_ORDER_GOODS};}
}

4、测试类

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes=Application.class)// 指定spring-boot的启动类
public class InspectionTest {@Autowiredprivate InspectionSolverChooser chooser;@Testpublic void test() throws Exception{//准备数据String taskType = InspectionConstant.INSPECTION_TASK_TYPE_BATCH_CHANGE_WAREHOUSE;Long orderId = 12345L;Long userId = 123L;//获取任务类型对应的solverInspectionSolver solver = chooser.choose(taskType);if (solver == null) {throw new RuntimeException("任务类型暂时无法处理!");}//调用不同solver的方法进行处理solver.solve(orderId,userId);}
}

在测试类中我消除了可能一长段的if else,从选择器InspectionSolverChooser中根据type的不同取出不同的任务处理器InspectionSolver,然后调用其solve()方法进行任务处理,不同处理器调用的当然就是不同的solve()方法了,目的达到。

业务代码中,太多 if else 怎么办?相关推荐

  1. JVM 性能调优实战之:使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码...

    本文是<JVM 性能调优实战之:一次系统性能瓶颈的寻找过程> 的后续篇,该篇介绍了如何使用 JDK 自身提供的工具进行 JVM 调优将 TPS 由 2.5 提升到 20 (提升了 7 倍) ...

  2. 天天写业务代码?写业务代码中的成长机会!

    写业务代码有成长机会吗?关于这个问题,答案非常肯定:必须有成长机会.对于大部分公司而言,能够写底层代码或者中间件代码的人总是有限的,写业务代码会面临更高的复杂度. 这里分三个层次来看其中的成长机会. ...

  3. 为什么spring中的controller跳转出错_你的业务代码中Spring声明式事务处理正确了吗?

    Spring 针对 Java Transaction API (JTA).JDBC.Hibernate 和 Java Persistence API(JPA) 等事务 API,实现了一致的编程模型,而 ...

  4. xxljob在业务代码中添加任务(登录后token验证)

    之前做过一次在业务代码中调用xxljob的接口添加任务启动任务,xxljob的接口添加免登录验证注解后直接调用,博文地址:xxl-job 在业务代码中添加任务,后面用到的groupId获取方法也在这里 ...

  5. 处理业务代码中循环遍历出现的性能问题

    在开发中很多场景下我们都会用到foreach循环遍历一个list,并在内部通过sql再去查询对应的数据,代码如下 public void test(){// 获取知识点关联数据List<Know ...

  6. 解决 SVN提交代码中太多其他无关文件的问题

    1.案例: 2.解决: 第一步:多选要提交的代码文件 第二步:右击项目选择Team-提交 第三步:写代码说明,点击提交 注:如果不放心代码,可以选择"Team"-"与资源 ...

  7. 天天写业务代码,如何成为技术大牛

    程序员平时的日常编码工作中,大多数人都只是编写业务代码,各种if else以及数据库操作等.针对于不同的产品去实现功能时,也只是重复性的搬砖工作.此时会有很多人认为天天写业务代码,感觉没有什么长进,也 ...

  8. 春节期间,我用责任链模式重构了业务代码

    前言 文章开篇,抛出一个老生常谈的问题,学习设计模式有什么作用? 设计模式主要是为了应对代码的复杂性,让其满足开闭原则,提高代码的扩展性 另外,学习的设计模式 一定要在业务代码中落实,只有理论没有真正 ...

  9. 大牛养成指南(3):天天写业务代码,如何成为技术大牛?

    2019独角兽企业重金招聘Python工程师标准>>> 几个典型的误区 拜大牛为师 知乎上有人认为想成为技术大牛最简单直接.快速有效的方式是"拜团队技术大牛为师" ...

最新文章

  1. 鱼油账号记录程序 - 零基础入门学习Delphi38
  2. SQLServer2008 Transact_SQL语言基础实例
  3. Android -- 发送Broadcast、有序无序
  4. WinCE程序的几种开发方法
  5. 牛客21783 牛牛的星际旅行
  6. Tomcat的三个端口
  7. 数据分析李小璐PG one出轨门自卫反击战
  8. C++:_ASSERTE(__acrt_first_block == header)
  9. 使用pip安装opencv
  10. 重写equals()时为什么也得重写hashCode()之深度解读equals方法与hashCode方法渊源
  11. 移动项目工作笔记0001---使用uni-app开发移动端应用
  12. JQuery与springmvc实现单个文件上传操作
  13. css放服务器ttf文件格式,CSS如何实现读取服务器字体
  14. Objective-C中的UIScrollView
  15. iostream头文件简单理解
  16. Oracle索引原理
  17. 基于QT和C++实现的停车场管理系统
  18. linux中su 与su-的区别
  19. 搜索邻近计算机打印机,在活动目录中设置和管理发布打印机
  20. 关于腾讯云域名访问问题的几个可能解决方案

热门文章

  1. OpenCV中OpponentColorDescriptorExtractor
  2. 带参数二维码如何跟踪用户来自哪个推广人员?
  3. 前端面试题-数组去重和排序
  4. Android我的便签-----SQLite的使用方法
  5. Zabbix 安装部署
  6. putty network error: connection refused
  7. 高性能网络编程1----accept建立连接
  8. JS Math对象中一些小技巧
  9. 美国互联网广告07年总开支255亿美元, 增长27%
  10. ADO.NET开发总结(学习笔记)