zoukankan      html  css  js  c++  java
  • 月下无限连?拒绝无休止switch!

    拒绝无休止switch


    一、前言

      前天碰到个需求,其实很简单,就是Excel导入,Excel模板长下面这样:

       

      按我平常的逻辑是这样做的:

    •   用文件输入流读取Excel,根据Excel的版本生成不同的对象,比如XSSFWorkbook或是HSSFWorkbook
    •        new一个工作簿,读取内容
    •        按行遍历,按cell单元格读取
    •        读取到值后,根据业务逻辑进行处理,最后存入entity

      这个需求按这个逻辑下来,循环取值的代码是这样的:

      

     1 if (CollectionUtils.isNotEmpty(rowList)) {
     2     List<DtTableCheck> data = Lists.newArrayList();
     3     Map<String, String> paramValueMap;
     4     for (int i = 0; i < rowList.size(); i++) {
     5         paramValueMap = Maps.newLinkedHashMap();
     6         DtTableCheck dtc = new DtTableCheck();
     7         for (Entry<String, String> entry : rowList.get(i).entrySet()) {
     8             switch (entry.getKey().trim()) {
     9                 case "检查编号":
    10                     //一堆业务处理
    11                 case "数据库":
    12                     //一堆业务处理
    13                 case "表":
    14                     //一堆业务处理
    15                 case "限制条件":
    16                     //一堆业务处理
    17                 case "检查规则":
    18                     //一堆业务处理
    19                 case "参数1":
    20                     //一堆业务处理
    21                 case "参数2":
    22                     //一堆业务处理
    23                 case "参数3":
    24                     //一堆业务处理
    25                 case "参数4":
    26                     //一堆业务处理
    27             }
    28         }
    29         data.add(dtc);
    30     }

    注:原先的代码过于丑陋,所以用了我司封装的方法,将Excel内容读取到一个list中,再循环读取,可以看到代码依然冗长

      这样做有一个问题,如果Excel模板变动或是业务逻辑变动,会牵一发而动全身,后端代码都要改,而且这样的代码可维护性极差,典型的面向过程编程。

      于是,趁着周末,借助策略模式与工厂模式的思想,赶紧重构了代码。


    二、重构

      代码中重复的操作是频繁的根据Excel单元格名称去switch不同的处理逻辑,那我们把它抽离出来,即

      

    1 /**
    2  * 解析Excel数据
    3  * @Author Cone
    4  * @Date 2019/12/7 12:39
    5  */
    6 public interface dealExcel {
    7 
    8     void deal(Map.Entry<String, String> entry, DtTableCheck dtc);
    9 }

      传入map中的一个要素,和需要操作的entity,具体的业务处理由不同的实现类去做。

      接下来我们写一个工厂,用来返回不同的实现类:

      

     1 /**
     2  * @Author Cone
     3  * @Date 2019/12/7 12:49
     4  */
     5 public class dealFactory {
     6 
     7     private static Map<String, dealExcel> dealMaps = Maps.newConcurrentMap();
     8 
     9     public static dealExcel create(String name) {
    10         return dealMaps.get(name);
    11     }
    12 
    13     public static void register(String name, dealExcel de) {
    14         dealMaps.put(name, de);
    15     }
    16     
    17 }

      dealMaps用来保存字段名称(比如检查编号、数据库、表等)和对应的操作实现类,create()方法根据传入的字段名称返回对应的实现类,register()方法则将字段名称与实现类保存到dealMaps中供我们调用。

      这样听起来好像没什么问题,但是我什么时候注册这个实现类到dealMaps中去呢?我们以一个实现类来举例:

      

     1 /**
     2  * 处理限制条件字段
     3  * @Author Cone
     4  * @Date 2019/12/7 13:16
     5  */
     6 @Service
     7 public class dealQueryCondition implements dealExcel, InitializingBean {
     8     @Override
     9     public void deal(Map.Entry<String, String> entry, DtTableCheck dtc) {
    10         dtc.setQueryCondition(null == entry.getValue() ? null : entry.getValue().trim());
    11     }
    12 
    13     @Override
    14     public void afterPropertiesSet() throws Exception {
    15         dealFactory.register("限制条件", this);
    16     }
    17 }

      这个实现类用来处理 Excel中 “限制条件”这一字段,我们在deal()方法中去完成具体的处理逻辑。接下来重点来了,可以看到,这个类还实现了一个接口,即InitializingBean,它是Spring提供的,这个接口里面有一个方法afterPropertiesSet(),用来做属性初始化后的相关操作,凡是继承该接口的类,在bean的属性初始化后,都会执行该方法,我们这里将实现类注册进去。

      接下来就很简单了,只需要根据业务去完成实现类即可。这样改造完后,程序的调用是这样的:

      

     1 List<Map<String, String>> rowList = ExcelHelper.readExcelSheet(file.getPath());
     2 if (CollectionUtils.isNotEmpty(rowList)) {
     3 
     4     for (int i = 0; i < rowList.size(); i++) {
     5         DtTableCheck dtc = new DtTableCheck();
     6         for (Entry<String, String> entry : rowList.get(i).entrySet()) {
     7             dealExcel de = dealFactory.create(entry.getKey());
     8             de.deal(entry, dtc);
     9         }
    10         
    11     }
    12     
    13 }

      rowList即为Excel中的数据,数据按行存入list,每一行的数据被放入map中,类似这样:

      

    1 [
    2   "检查编号":value,
    3   "数据库":value,
    4   "限制条件":value          
    5 ]

      改造后的效果不用我多说了。


    三、结语

      我之所以要改造原有代码是因为这个需求在不断变化,模板也在调整,但是如果Excel本来就2,3个字段,或者业务变动不大,那我觉得就没有必要做改造了,改造成本,开发效率需要自己去权衡。运用设计模式应该让代码更好维护,而不是更糟,对吧。

  • 相关阅读:
    thinkphp的钩子的两种配置和两种调用方法
    php闭包实现函数的自调用,也是递归
    php的spl_autoload_register函数的一点个人见解
    详解js变量、作用域及内存
    关于js的call()和apply()两个函数的一点个人看法
    php实现斐波那契数列以及由此引起的联想
    php猴子称王或者约瑟夫难题
    Linux Bash Shell 快速入门
    Fedora14下首次搭建Samba服务器遇到的一些问题
    【JavaScript】我的JavaScript技术总结第一篇——编程细节
  • 原文地址:https://www.cnblogs.com/cone/p/12002913.html
Copyright © 2011-2022 走看看