策略+工厂+反射记录一次switch代码简化过程

2023-11-05

遇到的问题:一张记录表,记录了10个业务的字段,一个入参type说明了要修改哪个字段,最初是通过switch(type)case…来做的

但是涉及这样子的判断多了,每次都要不断的switch,并且case里面不同方法有不同的处理,一个公共的switch并不能够满足

又不能在每一个方法中都写一个10个case的switch,代码太过臃肿了,因而产生了今天的记录,当然更加臃肿的if else更加能够简化啦

利用策略+工厂+反射,简化臃肿的switch

一、常量映射类

  • 现在定义一个常量类,表示了type和方法的映射
public enum LeaveTypeEnum {
    CASUAL_LEAVE("事假","setCasualLeave","setClBackup","getCasualLeave","getClBackup","setCasual","getCasual"),
    SICK_LEAVE("带薪病假","setSickLeave","setSlBackup","getSickLeave","getSlBackup","setSick","getSick"),
    SICK_LEAVE_NORMAL("普通病假","setSickLeaveNormal","setSlnBackup","getSickLeaveNormal","getSlnBackup", "setSickNormal", "getSickNormal"),
    MARRIAGE_LEAVE("婚假", "setMarriageLeave", "setMlBackup", "getMarriageLeave", "getMlBackup", "setMarriage", "getMarriage"),
    FUNERAL_LEAVE("丧假", "setFuneralLeave", "setFlBackup", "getFuneralLeave", "getFlBackup", "setFuneral", "getFuneral"),
    MATERNITY_LEAVE("产假","setMaternityLeave","setMnlBackup","getMaternityLeave","getMnlBackup","setMaternity","getMaternity"),
    MATERNITY_LEAVE_1("产假-难产假", "setMaternityLeave", "setMnlBackup", "getMaternityLeave", "getMnlBackup", "", ""),
    MATERNITY_LEAVE_2("产假-多胞胎假","setMaternityLeave","setMnlBackup","getMaternityLeave","getMnlBackup","",""),
    MATERNITY_LEAVE_3("产假-哺乳假", "setMaternityLeave", "setMnlBackup", "getMaternityLeave","getMnlBackup","",""),
    MATERNITY_LEAVE_4("产假-产检假", "setMaternityLeave", "setMnlBackup", "getMaternityLeave", "getMnlBackup", "setMaterPaternity","getMaterPaternity"),
    MATERNITY_LEAVE_5("产假-流产假", "setMaternityLeave", "setMnlBackup", "getMaternityLeave", "getMnlBackup", "", ""),
    PATERNITY_LEAVE("陪产假","setPaternityLeave","setPnlBackup","getPaternityLeave","getPnlBackup","setMaterPaternity","getMaterPaternity"),
    ANNUAL_LEAVE("年假", "setAnnualLeave", "setAlBackup", "getAnnualLeave", "getAlBackup", "setAnnual", "getAnnual");


    private String name;
    private String setMethod;
    private String setSubMethod;
    private String getMethod;
    private String getSubMethod;
    private String setCalMethod;
    private String getCalMethod;

    LeaveTypeEnum(String name,String setMethod,String setSubMethod,String getMethod,String getSubMethod,String setCalMethod,String getCalMethod) {
        this.name = name;
        this.setMethod = setMethod;
        this.setSubMethod = setSubMethod;
        this.getMethod = getMethod;
        this.getSubMethod = getSubMethod;
        this.setCalMethod = setCalMethod;
        this.getCalMethod = getCalMethod;
    }

    public String getName() {
        return name;
    }

    public static String getMethodByNameForSet(String name) {
        for (LeaveTypeEnum leaveType : LeaveTypeEnum.values()) {
            if (leaveType.name.equals(name)) {
                return leaveType.setMethod;
            }
        }
        return null;
    }

    public static String getSubMethodByNameForSet(String name) {
        for (LeaveTypeEnum leaveType : LeaveTypeEnum.values()) {
            if (leaveType.name.equals(name)) {
                return leaveType.setSubMethod;
            }
        }
        return null;
    }

    public static String getMethodByNameForGet(String name) {
        for (LeaveTypeEnum leaveType : LeaveTypeEnum.values()) {
            if (leaveType.name.equals(name)) {
                return leaveType.getMethod;
            }
        }
        return null;
    }

    public static String getSubMethodByNameForGet(String name) {
        for (LeaveTypeEnum leaveType : LeaveTypeEnum.values()) {
            if (leaveType.name.equals(name)) {
                return leaveType.getSubMethod;
            }
        }
        return null;
    }

    public static String getMethodByNameCalForSet(String name) {
        for (LeaveTypeEnum leaveType : LeaveTypeEnum.values()) {
            if (leaveType.name.equals(name)) {
                return leaveType.setCalMethod;
            }
        }
        return null;
    }

    public static String getMethodByNameCalForGet(String name) {
        for (LeaveTypeEnum leaveType : LeaveTypeEnum.values()) {
            if (leaveType.name.equals(name)) {
                return leaveType.getCalMethod;
            }
        }
        return null;
    }
}
  • 以上一个映射类和反射就能够解决问题,但是为了更简化并且利用上一些设计模式,就尝试了策略+工厂

二、 接口

public interface InvokeStrategy {
    Double getByColumn(String type,String leaveType,String methodName,Object obj);

三、接口实现类

  @Slf4j
  public class UserVacationInvokeHandler implements InvokeStrategy {
      @Override
      public Double getByColumn(String type,String leaveType,String methodName, Object obj) {
          UserVacation userVacation = (UserVacation) obj;
          try {
              Method method = UserVacation.class.getDeclaredMethod(methodName);
              Invokable<UserVacation, Object> invokable =
                      (Invokable<UserVacation, Object>) Invokable.from(method);
              Double invoke = (Double) invokable.invoke(userVacation);
              return invoke;
          }catch (Exception e ){
              log.error("方法调用失败,type:{},method:{}",type,methodName);
          }
          return null;
      }
  
      @Override
      public void setByColumn(String type, String leaveType,String methodName,Double param, Object obj) {
          UserVacation userVacation = (UserVacation) obj;
          try {
              Method method = UserVacation.class.getDeclaredMethod(methodName,Double.class);
              Invokable<UserVacation, Object> invokable =
                      (Invokable<UserVacation, Object>) Invokable.from(method);
             invokable.invoke(userVacation,param);
          }catch (Exception e ){
              log.error("方法调用失败,type:{},method:{}",type,methodName);
          }
      }
  }

四、策略工厂

public class InvokeStrategyFactory {
    private static InvokeStrategyFactory factory = new InvokeStrategyFactory();
    private InvokeStrategyFactory(){
    }
    private static Map<String,InvokeStrategy> strategyMap = new HashMap<>();
    static{
        strategyMap.put("UserVacation", new UserVacationInvokeHandler());
        strategyMap.put("UserVacationCal", new UserVacationCalInvokeHandler());
    }
    public InvokeStrategy creator(String type){
        return strategyMap.get(type);
    }
    public static InvokeStrategyFactory getInstance(){
        return factory;
    }

}

五、策略上下文

public class InvokeStrategyContext {
    private InvokeStrategy strategy;

    public Double getByColumn(String type, String leaveType, String methodName,Object obj) {
        strategy = InvokeStrategyFactory.getInstance().creator(type);
        return strategy.getByColumn(type, leaveType, methodName,obj);
    }

    public void setByColumn(String type, String leaveType,String methodName, Double param, Object obj) {
        strategy = InvokeStrategyFactory.getInstance().creator(type);
        strategy.setByColumn(type, leaveType,methodName, param, obj);
    }

    public InvokeStrategy getStrategy() {
        return strategy;
    }

    public void setStrategy(InvokeStrategy strategy) {
        this.strategy = strategy;
    }
}

六、使用

        InvokeStrategyContext context = new InvokeStrategyContext();
        Lock lock = new ReentrantLock();
        lock.lock();
        try {
        //只需这两行,就替换掉了一大堆的switch,并且能够轻松的进行中间操作,不再臃肿
            Double result = context.getByColumn("UserVacation", dto.getType(), methodOld, userVacation);
            context.setByColumn("UserVacation", dto.getLeaveType(), setMethod, result, userVacation);
        } catch (Exception e) {
            lock.unlock();
            log.error("更新uservation出现异常");
        } finally {
            lock.unlock();
        }

七、互联网上也不乏有一些方法

  • 传统反射
/***
 *定义每种类型所对应的方法
*/
public class ReflectTest {
    public void methodOne() {
        System.out.println("one");
    }

    public void methodTwo() {
        System.out.println("two");
    }

    public void methodThree() {
        System.out.println("three");
    }

    public void methodFour() {
        System.out.println("four");
    }

}

 /***
     *
     * 通过反射,动态调用方法。采用了Guava的工具类。
     * */
    @Test
    public void testReflect() throws Exception {
        //首字母大写,根据类型拼接方法
        String methodName = "method" + LOWER_CAMEL.to(UPPER_CAMEL, input);
        Method method = ReflectTest.class.getDeclaredMethod(methodName);
        Invokable<ReflectTest, Object> invokable =
                (Invokable<ReflectTest, Object>) Invokable.from(method);
        invokable.invoke(new ReflectTest());
    }
  • jdk8 lambda表达式
    public void testJava8() {
        Map<String, Consumer<ReflectTest>> functionMap = Maps.newHashMap();
        functionMap.put("one", ReflectTest::methodOne);
        functionMap.put("two", ReflectTest::methodTwo);
        functionMap.put("three", ReflectTest::methodThree);
        functionMap.put("four", ReflectTest::methodThree);
        functionMap.get(input).accept(new ReflectTest());
    }
  • 枚举
public enum EnumTest {


    ONE("one") {
        @Override
        public void apply() {
            System.out.println("one");
        }
    },
    TWO("two") {
        @Override
        public void apply() {
            System.out.println("two");
        }
    }, THREE("three") {
        @Override
        public void apply() {
            System.out.println("three");
        }
    }, FOUR("four") {
        @Override
        public void apply() {
            System.out.println("four");
        }
    };

    public abstract void apply();

    private String type;

    EnumTest(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }

}
  // 枚举测试
 @Test
    public void testEnum() {
        EnumTest.valueOf(input.toUpperCase()).apply();
    }

  • 我上面的方法其实结合了枚举和传统的反射,这边还看到了一个jdk8的实现,想必大家一定很好奇

八、jdk8的改造

  • 以上利用consumer执行了一个method,不带有返回值,我们执行set的方法的时候可以效法consumer,我们如果是get 怎么办呢?
  • 我们在使用Lambda表达式的时候,都会用到foreach和map两种算子,foreach接纳参数consumer,不带有返回值,map接纳参数function,可以有映射的值,这就引导我们意识到了function
//无返回参数
Map<String, Consumer<ReflectTest>> functionMap = Maps.newHashMap();
        functionMap.put("one", ReflectTest::methodOne);
        functionMap.put("two", ReflectTest::methodTwo);
        functionMap.put("three", ReflectTest::methodThree);
        functionMap.put("four", ReflectTest::methodThree);
        functionMap.get(input).accept(new ReflectTest());
//带返回参数

        Map<String, Function<ReflectTest,String>> map = Maps.newHashMap();
        map.put("one", ReflectTest::methodOne);
        map.put("two", ReflectTest::methodTwo);
        map.put("three", ReflectTest::methodThree);
        map.put("four", ReflectTest::methodThree);
        String apply = map.get("one").apply(new ReflectTest());
        System.out.println(apply);

//经测试,能够满足需求       
  • 那么枚举加传统反射也可以通过以上lambda表达式的方式改造啦,一个全局的静态的Map,接纳了关于set和get的定义,在使用的时候调用即可
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

策略+工厂+反射记录一次switch代码简化过程 的相关文章

  • 【html】【一个简单的用户登录页面代码】

    结果 代码
  • EasyPoi实现Excel数据导入

    EasyPoi是一个基于Java的Excel导入导出框架 主要提供了Excel读取 写入等基本功能 并且支持通过注解来定义Excel文件的格式 添加maven依赖
  • java的反射机制Class.forName()

    Class forName 方法的作用 就是初始化给定的类 1 Class 类概念 Class 也是一个 Java 类 保存的是与之对应 Java 类的 meta信息 元信息 用来描述这个类的结构 比如描述一个类有哪些成员 有哪些方法等 一
  • MySQL数据库入门超级详细教程

    文章目录 MySQL 1 数据库软件安装 2 为什么要用数据库 3 什么是数据库 4 数据库管理系统 DBMS 5 MySQL 介绍 6 SQL 6 1 SQL 语句概述 6 2 SQL 基本操作 7 表结构操作 7 1 创建数据表 7 2
  • Java通过反射获取注解以及注解中的信息

    首先自定义两个注解 1 用于描述表名 只能用在类 接口 枚举上 Target ElementType TYPE Retention RetentionPolicy RUNTIME public interface TableName Str
  • 数据库设计DDL

    DDL 数据定义语言 用来定义数据库对象 数据库 表 DDL 数据库操作 查询 查询所有数据库 show databases 查询当前数据库 select database 使用 使用数据库 use 数据库名 创建 创建数据库 create
  • 设计模式之六大原则

    设计模式之六大原则 转载 关于设计模式的六大设计原则的资料网上很多 但是很多地方解释地都太过于笼统化 我也找了很多资料来看 发现CSDN上有几篇关于设计模式的六大原则讲述的比较通俗易懂 因此转载过来 原作者博客链接 http blog cs
  • IDEA(最新版)导入Myeclipse/eclipse的web项目并运行(全) Windows或者Mac系统

    一 前言 最近在做毕业设计 没想到现在的大学中还是使用的Myeclipse比较多 这个工具逐渐被IDEA工具所代替 因为IDEA的性能和使用更加优秀 或者我们在工作中遇到Myeclipse项目导入IDEA中的情形 怎么将Myeclipse开
  • Springboot 实现发送邮件功能,使用QQ邮箱

    引入依赖
  • JavaWeb会话技术

    1 Cookie对象 cookie是一种会话技术 它用于将会话过程中的数据保存到用户的浏览器中 从而使浏览器和服务器可以更好的地进行数据交互 创建Serlet 创建一个chapter05项目 创建一个自己喜欢的包 在该包中编写一个为Last
  • errcode = 40163; errmsg = "code been used"(提供一种解决思路)

    最近在做微信开发 就在开发完毕测试的时候 遇到一个大问题 每次新用户进入的时候就报错 错误基本上就是code been used 我去百度了好久 没有找到合适的方案 后来我仔细的看了一下微信开发文档 终于解决了 注 该方法不一定对所有人有效
  • 行为型模式-策略模式

    package per mjn pattern strategy 抽象策略类 public interface Strategy void show package per mjn pattern strategy 具体策略类 用来封装算法
  • 使用session实现同一账号只能同时一个人使用

    使用session实现同一账号只能同时一个人使用 今天我们要讲的就是 实现同一个账号只能同一时间让一个人使用 实现起来也是非常的简单 其实我这里讲到的是我前几天做出来的一个大概核心代码和核心思路 我也是查遍了很多网站 看了很多人的源码然后都
  • Servlet3.0基础

    一 要求 1 MyEclipse10 0或以上版本 2 发布到Tomcat7 0或以上版本 二 步骤 1 创建javaEE6 0应用 三 概述 注解代替web xml配置文件 异步处理 对上传的支持 四 注解代替配置文件 1 删除web x
  • javaweb——Response下载文件

    HttpServletResponse web服务器接收到客户端的http请求 针对这个请求分别创建一个代表请求的HttpServletResponse对象 一个代表响应的HttpServletResponse对象 如果要获取客户端请求过来
  • java中如何将Long类型转为Integer类型

    注意不能直接在前面加个 int 而是 将Long型转换为int型 这里的Long型是包装类型 Long a 10 int b a intValue 即long intValue
  • 【EasyExcel】 模板填充批量导出,多文件以zip压缩包格式导出

    使用 阿里巴巴的 EasyExcel 填充 excel模板导出 需要支持批量操作 即一个模板循环导出多份 在网上找了下其他大佬们的做法 没有找到想要的 很多都是要先生成excel文件 再压缩导出 但我不想这样做 想直接通过文件流的方式 直接
  • response实现文件下载(java)

    import javax servlet ServletException import javax servlet ServletOutputStream import javax servlet http HttpServlet imp
  • 信号完整性分析基础知识之传输线和反射(一):阻抗变化引起反射

    阻抗不连续引起的反射和失真可能会导致信号的误触发和误码 这是导致信号失真和质量下降的主要原因 在某些情况下 这看起来像振铃 当信号电平下降时 下冲会影响噪声预算并导致误触发 或者 在下降信号上 峰值可能会上升到低位阈值以上并导致误触发 下图
  • 浏览器发器POST请求

    浏览器按F12或打开开发者工具 在console 控制台 标签页下输入 fetch new Request http localhost 8080 power font getToken method POST headers Conten

随机推荐

  • 4g网络设置dns地址_4G网速越来越慢,通过这三个简单的操作,网速成倍提升

    随着互联网的进步 从零几年开始移动手机在全国开始普及起来 网速也像火箭一样快速飙升 从2G发展到了现在的5G 不过 有很多网友表示 刚从2G或者3G升级到4G时 网速体验非常好 但近两年来的4G网速越来越慢 还卡顿 甚至感觉还不如以前的3g
  • 忘记网站服务器密码怎么办,忘记远程服务器的密码怎么办

    忘记远程服务器的密码怎么办 内容精选 换一换 如果在创建弹性云服务器时未设置密码 或密码丢失 过期 可以参见本节操作重置密码 密码丢失或过期前 已安装密码重置插件 公共镜像创建的弹性云服务器默认已安装一键重置密码插件 私有镜像创建的云服务器
  • Matlab—M_Map的实战学习笔记(一)M_Map库的安装

    最近在做美赛集训 做到了2020年的美赛A题 有关苏格兰附近鲭鱼和鲱鱼分布预测问题 在写论文的过程中 为了画几张精美的地图 可谓是历经千难万险 花费了不少时间 走了不少弯路 现在对使用matlab的m map映射库进行地图绘制做一个总结 力
  • Python:UnicodedecodeError编码问题解决方法汇总-彻底解决

    今天真的被编码问题一直困扰着 午休都没进行 也真的见识到了各种编码 例如 gbk unicode utf 8 ansi gb2312等 如果脚本程序中编码与文件编码不一致 就会报出UnicodedecodeError的错误 1 情景一 读文
  • python语法-面向对象(构造方法、魔术方法)

    python语法 面向对象 构造方法 魔术方法 1 构造方法 构造方法 python类可以使用 init 方法 称之为构造方法 可以实现 在创建类对象时 会自动执行 在创建类对象时 将传入参数自动传递给 init 方法使用 演示使用构造方法
  • Android中的定时器Timer、AlarmManager、CountDownTimer的使用

    1 Timer和TimerTask的使用 java util Timer定时器 实际上是个线程 定时调度所拥有的TimerTasks 1 创建一个Timer code class hljs cs has numbering style di
  • 解析 Linux 内核可装载模块的版本检查机制

    解析 Linux 内核可装载模块的版本检查机制 王 华东 系统工程师 自由职业者 简介 为保持 Linux 内核的稳定与可持续发展 内核在发展过程中引进了可装载模块这一特性 内核可装载模块就是可在内核运行时加载到内核的一组代码 通常 我们会
  • js获取到的时间减1秒或加1秒

    如题 使用时间戳来计算 function setDate time isAdd var date getCurTime time 也可以直接透传如 2021 5 8 var d new Date date var t s d getTime
  • 闲鱼把各种玩法做成了一个平台:哆啦A梦

    玩法平台背景 在闲鱼内我们把供给用户的闲鱼红包 支付宝红包 包邮券 宝卡等统称为用户权益 是闲鱼用户运营的重要策略 在拉新 留存 促活 裂变等方面都展现了其重要价值 在阿里内部管理权益的平台是拉菲 拉菲对外提供概率抽奖和领奖两种能力 各个业
  • 为什么gbk编码常用抽取正则表达式无法抽取“嘚瑟“的“嘚”字

    根据 GBK汉字内码扩展规范编码表 http ff 163 com newflyff gbk list 可以查到 嘚 字的编码为874e 而我们常用的gbk汉字抽取正则表达式为 x80 xff x80 xff 以python正则为例 抽取汉
  • Python基础--入门基础和数据类型测试题(二)

    Made By Zly All Right Reversed 上一篇 篇四 Python 入门基础和数据类型测试题 二 1 以下不属于Python语言保留字的是 A do B pass C while D def 2 表达式3 4 2 8
  • 第一讲 检索系统与数据库编程

    第一讲 检索系统与数据库编程 准备工作 1 检索系统 1 1 检索系统初识 1 1 1 什么是检索系统 1 1 2 从认知心理学看待检索系统 1 2 检索系统的四大法宝 1 2 1 检索的工具 结构化查询语言 SQL 1 2 2 检索的环境
  • Electron-builder打包和自动更新

    前言 文本主要讲述如何为 electron 打包出来软件配置安装引导和结合 github 的 release 配置自动更新 electron builder 是将 Electron 工程打包成相应平台的软件的工具 我的工程是使用 elect
  • C语言小知识点

    1 LPCSTR被定义成是一个指向以 0 结尾的常量字符指针 LPWSTR是wchar t字符串 例子 LPWSTR lpwstr NULL LPWSTR lp T asdfasgaf 2 之所以能够实现条件编译是因为预编译指令是在编译之前
  • HTTP请求头和响应头详解【转】

    最近老猿在开始学习爬虫相关的知识 由于老猿以前只做非web的后台应用 发现相关知识太过匮乏 导致学习很困难 为此不得不从一些基础知识恶补开始 对于这些知识 老猿会将网上找到的比较认可的内容直接转发 下面文章关于http头部信息讲解的非常详细
  • springboot笔记总结

    springboot 1 Javaconfig Configuration 放在类的上面 这个类相当于 xml 配置文件 可以在其中声明 bean Bean 放在方法的上面 方法的返回值是对象类型 这个对象注入到 spring ioc 容器
  • 字典排序算法(通俗易懂)

    我们先看一个例子 示例 1 2 3的全排列如下 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 我们这里是通过字典序法找出来的 那么什么是字典序法呢 从上面的全排列也可以看出来了 从左往右依次增大 对这就是字典序法
  • Java中 ? extends T 和 ? super T 的理解

    通配符类型
  • (转)如何有效地管理好技术团队?

    转自 https cn 100offer com blog posts 307 技术管理是一个综合性岗位 要求你具有技术能力 管理能力 也要懂一些心理学 情商也要高一些 说实话 你想做好这个岗位 真的不容易 尤其是在中国 我相信今天的分享过
  • 策略+工厂+反射记录一次switch代码简化过程

    遇到的问题 一张记录表 记录了10个业务的字段 一个入参type说明了要修改哪个字段 最初是通过switch type case 来做的 但是涉及这样子的判断多了 每次都要不断的switch 并且case里面不同方法有不同的处理 一个公共的