代码优雅之道——如何干掉过多的if else

news2024/11/15 15:28:09

1、前言

注意标题是过多的,所以三四个就没必要干掉了。实际开发中我们经常遇到判断条件很多的情况,比如下图有20多种情况,不用想肯定是要优化代码的,需要思考的是如何去优化?

网上很多说用switch case啊,首先不比较if else与switch case效率问题的,只从代码整洁度来看二者没啥区别啊!我们这里更重要的是代码整洁度问题,为什么呢?来看下文的比较。

2、If else与switch case效率真的差距很大么?

网上有两种见解:

第一种是说switch…case会生成一个跳转表来指示实际的case分支的地址,而这个跳转表的索引号与switch变量的值是相等的。从而,switch…case不用像if…else那样遍历条件分支直到命中条件,而只需访问对应索引号的表项从而到达定位分支的目的。简单来说就是以空间换时间

第二种是说二者效率上差距并不大

于是我们自己去体验一下,不存在复杂业务逻辑,仅仅比较两种方式的效率:

@Test
    void contextLoads() {
        testIf(100000);
        System.gc();
        testSwitch(100000);
    }

    private void testIf(Integer param) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < param; i++) {
            if (i == param-1){
                System.out.println("if判断100000次");
            }
        }
        long end = System.currentTimeMillis();
        long total = end - start;
        System.out.println("Test消耗时间:" + total);
    }

    private void testSwitch(Integer param){
        long start = System.currentTimeMillis();
        for (int i = 0; i < param; i++) {
            switch (i){
                case 99999:
                    System.out.println("switch判断100000次");
                    break;
            }
        }
        long end = System.currentTimeMillis();
        long total = end - start;
        System.out.println("Test消耗时间:" + total);
    }

可见差距并不大。而情况太多的时候谁还会去用if else和switch case呢?下面还是对两种方式的使用场景做简单的分析:

if else能够把复杂的逻辑关系表达得清晰、易懂,包容了程序执行的各种情况。

switch不适合业务系统的实际复杂需求,业务不断的变更迭代,一更改需求,条件的复杂度高了,switch无力处理。switch经常忘记写break,估计很多人一不小心就忘记写了。switch…case只能处理case为常量的情况。当情况不大于5种并且单一变量的值(如枚举),此时我们就可以使用switch,它的可读性比if条件更清晰。

除了上述说到枚举的这种场景,建议使用switch,其他个人愚见:只要情况不大于5种就直接使用if else

3、策略+工厂模式

上述说到情况较少时并且业务逻辑不复杂的使用if else可以让代码清晰明了。当每种情况对应的业务逻辑复杂时,建议使用策略+工厂模式。这里我们举个栗子:厂家每个季度要举行不同的活动,我们使用策略工厂模式来实现

策略接口

public interface Strategy {

    /**
     * 处理各种活动
     * @return
     */
    String dealActivity();
}

然后春夏秋冬四季活动类实现该接口

@Service
public class SpringActivity implements Strategy{
    @Override
    public String dealActivity() {
        return "春季活动逻辑";
    }
}

策略类工厂

public class StrategyFactory {
    public static Strategy execute(Integer levelCode){
        Strategy strategy = null;
        switch (levelCode){
            case 1:
                strategy = new SpringActivity();
                break;
            case 2:
                strategy = new SummerActivity();
                break;
            case 3:
                strategy = new AutumnActivity();
                break;
            case 4:
                strategy = new WinterActivity();
                break;
            default:
                throw new IllegalArgumentException("活动编号错误");
        }
        return strategy;
    }
}

然后在service层中传入对应的编码即可 ,我这里省略了service

@RestController
public class TestController {

    @PostMapping("/dealActivity")
    public String dealActivity(Integer code){
        Strategy strategy = StrategyFactory.execute(1);
        return strategy.dealActivity();
    }
}

上述已经干掉了if else ,后续季度活动调整去修改对应活动策略类中逻辑即可。缺点:如果情况比这多,那么策略类会越来越多,也就是所谓的策略类膨胀,并且没有****没有一个地方可以俯视整个业务逻辑。

4、Map+函数式接口

将上述策略类全部作为方法

@Service
public class ActivityStrategyService {

    public String dealSpringActivity(){
        return "春季活动逻辑";
    }

    public String dealSummerActivity() {
        return "夏季活动逻辑";
    }

    public String dealAutumnActivity() {
        return "秋季活动逻辑";
    }

    public String dealWinterActivity() {
        return "冬季活动逻辑";
    }
}

再写个活动Service

@Service
public class ActivityService {

    @Autowired
    private ActivityStrategyService activityStrategyService;

    @FunctionalInterface
    interface ActivityFunction<A>{
        //这里可以传参啊,我这里举例用不上参数
        //String dealActivity(A a);
     String dealActivity();
    }

    private final Map<Integer, ActivityFunction> strategyMap = new HashMap<>();

    /**
     * 初始化策略
     */
    @PostConstruct
    public void initDispatcher(){
        strategyMap.put(1,()->activityStrategyService.dealSpringActivity());
        strategyMap.put(2, ()-> activityStrategyService.dealSummerActivity());
        strategyMap.put(3, ()-> activityStrategyService.dealAutumnActivity());
        strategyMap.put(4, ()-> activityStrategyService.dealWinterActivity());
    }

    public String dealActivity(Integer code){
        ActivityFunction<Integer> function = strategyMap.get(code);
        //这里防止活动编号没匹配上,可以使用断言来判断从而抛出统一异常
        return function.dealActivity();
    }

}

改变Controller

@RestController
public class TestController {

    @Autowired
    private ActivityService activityService;

    @PostMapping("/dealActivity")
    public String dealActivity(Integer code){
//        Strategy strategy = StrategyFactory.execute(1);
//        return strategy.dealActivity();
        return activityService.dealActivity(code);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/459061.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法刷题|198.打家劫舍、213.打家劫舍Ⅱ、337.打家劫舍Ⅲ

打家劫舍 题目&#xff1a;你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定…

【社区图书馆】Fundamentals Of Computer Graphics——The beginning of computer graphics

目录 English 中文 English "Fundamentals Of Computer Graphics" is a classic textbook on computer graphics, also known as the "Tiger Book". It is considered one of the best introductory texts in the field of computer graphics. The book …

1分钟搭建自己的GPT网站

如果觉得官方免费的gpt&#xff08;3.5&#xff09;体验比较差&#xff0c;总是断开&#xff0c;或者不会fanqiang&#xff0c;那你可以自己搭建一个。但前提是你得有gpt apikey。年初注册的还有18美金的额度&#xff0c;4.1号后注册的就没有额度了。不过也可以自己充值。 有了…

【Redis】Redis事务

介绍 可以一次执行多个命令&#xff0c;本质是一组命令的集合。一个事务中的所有命令都会序列化&#xff0c; 按顺序地串行化执行而不会被其他命令插入一个队列中&#xff0c;一次性、顺序性、排他性的执行一系列命令没有隔离级别的概念&#xff0c;没有脏读、不可重复读等。 …

思维导图从入门到大神

思维导图怎么做&#xff1f;思维导图是一种发散性思维的图。在我们生活的方方面面都有运用。无论是工作、学习、还是生活&#xff0c;我们都可以用到它。那思维导图是怎么绘制的呢&#xff1f;其实非常简单&#xff0c;只要这简单的几步 1、首先在绘制思维导图前&#xff0c;我…

veImageX 演进之路:iOS 高性能图片加载 SDK

动手点关注 干货不迷路 1. SDK简介 图片在业务应用场景是一个常见的元素&#xff0c;veImageX&#xff08;简称ImageX&#xff09;为业务提供了灵活、高效的一站式图片处理解决方案&#xff0c;包括了服务端 SDK、上传 SDK 和客户端图片加载 SDK。本文就来介绍下 iOS 客户端图…

力扣 1493(删掉一个元素以后全为 1 的最长子数组)Java

目录 题目 约束 用例 解题思路 各位看官先看执行结果 这道题呢&#xff0c;采用的滑动窗口思想。 题目 给你一个二进制数组 nums &#xff0c;你需要从中删掉一个元素。 请你在删掉元素的结果数组中&#xff0c;返回最长的且只包含 1 的非空子数组的长度。 如果不存在…

15天学习MySQL计划-索引(进阶篇)第七天

索引 1.索引概述 1.介绍 索引&#xff08;index&#xff09;是帮助MySQL高效获取数据的数据结构&#xff08;有序&#xff09;。在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构&#xff0c;这些数据结构以某种方式引用&#xff08;指向&#xff09;数…

HTTP1.1(十二)Cookie的格式与约束

一 Cookie的格式与约束 ① Cookies是什么 1) cookie是我们在前端编程中经常使用的概念2) 使用cookie利用浏览器帮助我们保存客户的相关状态信息,保存用户已经做了什么事情3) 重点和难点[1]、cookie的工作原理[2]、cookie的限制是什么[3]、session又是怎样与cookie关联起来 …

【Android Framework (七) 】- ActivityManagerService(AMS)

文章目录 知识回顾启动第一个流程initZygote的流程system_serverServiceManagerBinderLauncher的启动 前言源码分析1.AMS的启动. ActivityManagerService.java2.setSystemProcess3.应用进程的初始化4.Activity的启动流程 拓展知识1.介绍一下Activity的启动流程。2.ActivityMana…

Handbook of MusicPsychology 音乐心理学手册 ( 多纳德·霍杰斯 Donald.A.Hodges) 笔记

由两个以上的音组成的结合音&#xff0c;除了该声波的波形&#xff0c;人耳会另外脑补出不存在的波形 频率相距较远的一些音与频率相距较近的一些音&#xff0c;前者累加的响度比后者要大 除了泛音部分&#xff0c;音的起声部分也是音色辨别的关键 音高、响度、音色、时值&a…

托福高频真词List07 // 附托福TPO阅读真题

目录 ​ 4月24日单词 生词 熟词 4月25日真题 4月24日单词 生词 &#x1f361;live in strictly aquatic habitat / əˈkwɑːtɪk / &#x1f361;only live in aquatic environment 只生活在水生环境中 readilyquickly readilyeasily adv 迅速地 adv 轻易地 wide…

聚观早报|中国将是ChatGPT主要对手;​iPhone 15将使用USB-C接口

今日要闻&#xff1a;中国将是ChatGPT主要对手&#xff1b;iPhone 15将使用USB-C接口&#xff1b;31名ChatGPT训练派遣工遭解雇&#xff1b;大疆Mavic 3 Pro无人机高清图曝光&#xff1b;中国红牛回应被禁止生产销售 中国将是ChatGPT主要对手 微软总裁布拉德史密斯接受采访时表…

前端开发之vue动态路由实现方案

前端开发之vue动态路由实现方案 前言2. 实现1、登录页面创建登录函数和watch监听路由2、调用的login方法&#xff08;1&#xff09;登录方法&#xff08;2&#xff09;存储token 3、router.push的时候调用路由守卫&#xff08;1&#xff09;创建路由守卫&#xff0c;建议路由守…

MySQL Community Server 8.0.33安装教程【笔记】

仅安装MySQL Community Server 下载网址&#xff1a;https://dev.mysql.com/downloads/installer/ 1、下载对应版本&#xff1b; 2、下载后&#xff0c;双击安装&#xff0c;弹出界面选择【Custom】&#xff1b; 3、弹出界面选择【MySQL Server 8.0.33 - X64】; 3、弹出界面…

【C++ Metaprogramming】0. 在C++中实现类似C#的泛型类

两年前&#xff0c;笔者因为项目原因刚开始接触C&#xff0c;当时就在想&#xff0c;如果C有类似C#中的泛型限定就好了&#xff0c;能让代码简单许多。我也一度认为&#xff1a; 虽然C有模板类&#xff0c;但是却没办法实现C#中泛型特有的 where 关键词&#xff1a; public c…

Android 13 wificond讲解

wificond介绍 看如下图,可以知道wificond 进程,该进程位于 system/connectivity/wificond 中。wificond 进程通过标准的 nl80211 命令与 Wi-Fi 驱动程序进行通信。 查看手机也能看到wificond 进程 wificond启动 1. 开机的时候通过调用wificond.rc文件启动wificond system…

docker 部署LNMP

准备工作。 #首先获取nginx配置文件 [rootlocalhost ~]# docker pull nginx:1.23.3 [rootlocalhost ~]# docker run --name nginx --restartalways -d -p 80:80 nginx:1.23.3 [rootlocalhost ~]# mkdir -p /usr/local/nginx/{conf,log,html,conf.d} #复制配置文件 [rootlocalh…

易观千帆 | 2023年3月证券APP月活跃用户规模盘点

易观&#xff1a;2023年3月证券服务应用活跃人数14131.58万人&#xff0c;相较上月&#xff0c;环比增长0.61%&#xff0c;同比增长0.60%&#xff1b;2023年3月自营类证券服务应用Top10 活跃人数6221.44万人&#xff0c;环比增长0.08%&#xff1b;2023年3月第三方证券服务应用T…

使用Spring的五大类注解读取和存储Bean

目录 1.存储Bean对象的注解 1.1 五大类注解 1.2 方法注解 1.3添加注解的依赖 2.注解的使用 2.1 controller注解 2. 2Service注解 2.3.Resopsitory注解 2.4Component注解 2.5Configuration注解 2.6 注解之间的关系 3.方法注解 3.1 方法注解要配合类注解来使用。 3.2…