if...else绝佳替换方案

目录

    • 方法一:提前 return
    • 方法二:枚举
    • 方案三:Optional 判空
    • 方案四:表驱动法
    • 方案五:策略模式 + 工厂方法
    • 方案六:责任链模式
    • 方案七:Function

在这里插入图片描述

方法一:提前 return

假如有如下代码:

if (condition){
  doSomething;
} else {
  return;
}

这种代码我们一般采用提前 return 的方式,去掉不必要的 else。

if (!condition){
  return
}

doSomething;

这种方法一般只适合分支结构很简单的 if…else,我们可以提前 return ,把一些不必要的 if…else 去掉。

方法二:枚举

枚举其实也是可以去掉 if…else 的,如下:

String orderStatusDes;
if ("1".equals(orderStatus)) {
    orderStatusDes = "订单未支付";
} else if ("2".equals(orderStatus)) {
    orderStatusDes = "订单已支付";
} else if ("3".equals(orderStatus)) {
    orderStatusDes = "订单已发货";
} else if ("4".equals(orderStatus)) {
    orderStatusDes = "订单已签收";
} else if ("5".equals(orderStatus)) {
    orderStatusDes = "订单已评价";
}

可能有小伙伴说,靠,谁会写这种代码?别这么绝对,大明哥工作这么久了,到现在依然看到有工作 5 、6 年的人写这样的代码。这种类型的代码非常适合枚举来解决。
先定义一个枚举类:

@Getter
@AllArgsConstructor
public enum OrderStatusEnum {
    UN_PAID("1","订单未支付"),
    PAIDED("2","订单已支付"),
    SENDED("3","订单已发货"),
    SINGED("4","订单已签收"),
    EVALUATED("5","订单已评价");
    
    private String status;
    private String statusDes;
    static OrderStatusEnum of(String status) {
        for (OrderStatusEnum statusEnum : OrderStatusEnum.values()) {
            if (statusEnum.getStatus().equals(status)) {
                return statusEnum;
            }
        }
        return null;
    }
}

有了这个枚举,上面代码直接可以优化为一行代码:

String orderStatusDes = OrderStatusEnum.of(orderStatus).getStatusDes();

当然一般在实际项目中,这种处理方式也不是最佳的,最佳的方式应该是在数据库里面有一个码值配置表,然后加载到系统缓存中来,在通过 code 去取值。当然枚举也是一种很好的解决方案。

方案三:Optional 判空

我相信各位小伙伴的项目里面一定存在非空判断,如果为空,则抛出异常或者 return。

Order order = getOrderById(id);
if (order == null) {
    return "-1";
} else {
    return order.getOrderStatus();
}

对于这种代码我们利用 Optional 可以非常优雅地解决。

return Optional.ofNullable(order).map(o -> o.getOrderStatus()).orElse("-1");

这种方式是不是非常优雅,有格调。最后补充一句:

防止 NPE,是程序员的基本修养

方案四:表驱动法

表驱动法,是一种让你可以在表中查找信息,而不必用过多的 if…else 来把他们找出来的方法。如下:

if ("code1".equals(action)) {
    doAction1();
} else if ("code2".equals(action)) {
    doAction2();
} else if ("code3".equals(action)) {
    doAction3();
} else if ("code4".equals(action)) {
    doAction4();
} else if ("code5".equals(action)) {
    doAction5();
}

优化方法如下:

Map<String, Function<?> action> actionMap = new HashMap<>();
action.put("code1",() -> {doAction1()});
action.put("code2",() -> {doAction2()});
action.put("code3",() -> {doAction3()});
action.put("code4",() -> {doAction4()});
action.put("code5",() -> {doAction5()});

// 使用

actionMap.get(action).apply();

其实这种方式也不是很好,因为它会显得代码非常臃肿。一种变形方案是将 doAction() 抽象成类。如下:
//1. 先定义一个 ActionService 接口

public interface ActionService {
    void doAction();
}

//2. 然后定义 5 个实现类

public class ActionService1 implements ActionService{
    public void doAction() {
        //do something
    }
}

//3. 加入表中

Map<String, ActionService> actionMap = new HashMap<>();
action.put("code1",new ActionService1());
action.put("code2",new ActionService2());
action.put("code3",new ActionService3());
action.put("code4",new ActionService4());
action.put("code5",new ActionService5());

//4. 调用

actionMap.get(action).doAction();

这种方式是不是比较优雅些!

方案五:策略模式 + 工厂方法

策略模式 + 工厂方法是解决 if…else 用得非常多的方案,它和上面的表驱动法有点儿类似。使用策略模式 + 工厂方法分为几个步骤,以上面例子为例:

把条件模块抽象为一个公共的接口,策略接口

public interface ActionService {
    void doAction();
}

根据每个逻辑,定义出自己具体的策略实现类,如下:

public class ActionService1 implements ActionService{
    public void doAction() {
        //do something
    }
}
public class ActionService2 implements ActionService{
    public void doAction() {
        //do something
    }
}

// 省略其他策略

工厂类,统一调度,用来管理这些策略,如下:

public class ActionServiceFactory {
    private ActionServiceFactory(){

    }
    
    private static class SingletonHolder{
        private static ActionServiceFactory instance=new ActionServiceFactory();
    }

    public static ActionServiceFactory getInstance(){
        return SingletonHolder.instance;
    }

    private static final Map<String,ActionService> ACTION_SERVICE_MAP = new HashMap<String, ActionService>();

    static {
        ACTION_SERVICE_MAP.put("action1",new ActionService1());
        ACTION_SERVICE_MAP.put("action2",new ActionService2());
        ACTION_SERVICE_MAP.put("action3",new ActionService3());
        ACTION_SERVICE_MAP.put("action4",new ActionService4());
        ACTION_SERVICE_MAP.put("action5",new ActionService5());
    }

    public static ActionService getActionService(String actionCode) {
        ActionService actionService = ACTION_SERVICE_MAP.get(actionCode);
        if (actionService == null) {
            throw new RuntimeException("非法 actionCode");
        }
        return actionService;
    }

    public void doAction(String actionCode) {
        getActionService(actionCode).doAction();
    }
}

单例模式实现工厂类。

使用

ActionServiceFactory.getInstance().doAction("action1");

这种优化方式也是很优雅的,特别适合分支较多,逻辑较为复杂的代码块,这种方式将分支逻辑与业务代码解耦了,是一种很不错的方案。

方案六:责任链模式

你想不到责任链模式也能优化 if…else 吧。责任链我们可以看做是一个单链表的数据结构,一个对象一个对象地过滤条件,符合的就执行,然后结束,不符合的就传递到下一个节点,如果每个对象都无法处理,一般都有一个最终的节点来统一处理。
我们依然以上面那个例子为例。

定义责任链处理请求节点

public abstract class ActionHandler {

    // 后继节点
    protected ActionHandler successor;

    /**
     * 处理请求
     * @param actionCode
     */
    public void handler(String actionCode) {
        doHandler(actionCode);
    }

    // 设置后继节点
    protected ActionHandler setSuccessor(ActionHandler successor) {
        this.successor = successor;
        return this;
    }

    // 处理请求
    public abstract void doHandler(String actionCode);
}

定义首尾节点,用于一些异常情况的处理

// 首节点,判断 actionCode 是否为空

public class HeadHandler extends ActionHandler{

    @Override
    public void doHandler(String actionCode) {
        if (StringUtils.isBlank(actionCode)) {
            throw new RuntimeException("actionCode 不能为空");
        }

        successor.doHandler(actionCode);
    }
}

// 尾节点,直接抛出异常,因为到了尾节点说明当前 code 没有处理

public class TailHandler extends ActionHandler{

    @Override
    public void doHandler(String actionCode) {
        throw new RuntimeException("当前 code[" + actionCode + "] 没有具体的 Handler 处理");
    }
}

定义各个节点具体的实现节点

public class ActionHandler1 extends ActionHandler{

    @Override
    public void doHandler(String actionCode) {
        if ("action1".equals(actionCode)) {
            doAction1();
        } else {
            // 传递到下一个节点
            successor.doHandler(actionCode);
        }
    }
}

public class ActionHandler2 extends ActionHandler{

    @Override
    public void doHandler(String actionCode) {
        if ("action2".equals(actionCode)) {
            doAction2();
        } else {
            // 传递到下一个节点
            successor.doHandler(actionCode);
        }
    }
}

// 省略其他节点

定义工厂,来构建一条完整的责任链,并负责调度

public class ActionHandlerFactory {
    
    private ActionHandler headHandler;
    
    private ActionHandlerFactory(){
        headHandler = new HeadHandler();
        ActionHandler actionHandler1 = new ActionHandler1();
        ActionHandler actionHandler2 = new ActionHandler2();
        ActionHandler actionHandler3 = new ActionHandler3();
        ActionHandler actionHandler4 = new ActionHandler4();
        ActionHandler actionHandler5 = new ActionHandler5();

        ActionHandler tailHandler = new TailHandler();
        
        // 构建一条完整的责任链
        headHandler.setSuccessor(actionHandler1).setSuccessor(actionHandler2).setSuccessor(actionHandler3).
                setSuccessor(actionHandler4).setSuccessor(actionHandler5).setSuccessor(tailHandler);
    }

    private static class SingletonHolder{
        private static ActionHandlerFactory instance=new ActionHandlerFactory();
    }

    public static ActionHandlerFactory getInstance(){
        return SingletonHolder.instance;
    }
        
    public void doAction(String actionCode) {
        headHandler.doHandler(actionCode);
    }
}

使用

ActionHandlerFactory.getInstance().doAction("action1");

方案七:Function

Function 是 Java 8 中的函数式接口,利用好它我们可以极大地简化我们的代码,例如利用它我们可以轻松去掉我们的 if…else。比如有下面一段代码:

// 抛出异常
if (...) {
  throw new RuntimeException("哎呀,有异常哦...")
}

// if...else 分支
if(...) {
  doSomething1();
} else {
  doSomething2();
}

现在我们利用 Function 来处理上面两段代码
处理抛出异常

定义抛出异常的形式的函数式接口

@FunctionalInterface
public interface ThrowExceptionFunction {

    /**
     * 抛出异常
     * @param message
     */
    void throwMessage(String message);
}

这里只需要有一个这样的函数式接口就行,而且方法也没有返回值,是一个消费型接口。

增加判断工具类

public class ValidateUtils {

    /**
     * 抛出异常
     * @param flag
     * @return
     */
    public static ThrowExceptionFunction isTrue(Boolean flag) {
        return (errorMessage) -> {
            if (flag) {
                throw new RuntimeException(errorMessage);
            }
        };
    }
}

ValidateUtils 类也是非常简单的,如果传入的 flag 为 true,则抛出异常。isTrue() 返回值也是刚刚我们定义的 ThrowExceptionFunction。

使用

ValidateUtils.isTrue(flag).throwMessage("哎呀,有异常哦...");

使用方式是不是非常简单?
处理 if…else 分支
其实使用 Function 来去掉 if…else 分支我认为有点儿偏门,因为它非常依赖我们定义的 Function 函数,比如我们定义的方法只有两个参数,那它就只能处理处理两个分支的,对于三个分支的 if…else 则需要重新定义方法。下面以两个分支为例。

定义函数式接口

@FunctionalInterface
public interface ActionHandler {
    void doActionHandler(ActionService trueActionService,ActionService falseActionService);
}

函数式接口中定义了一个方法,doActionHandler(),它有两个参数,分别为:

trueActionService:为 true 时要进行的操作
falseActionService:为 false 时要进行的操作

定义判断方法

增加一个工具类,用来判断为 true 时执行哪个方法,为 false 时执行哪个方法。

public class ActionHandlerUtils {

    public static ActionHandler isTrue(Boolean flag) {
        return (trueActionService,falseActionService) -> {
            if (flag) {
                trueActionService.doAction();
            } else {
                trueActionService.doAction();
            }
        };
    }
}

使用

ActionHandlerUtils.isTrue(true)
        .doActionHandler(() -> {
            //do true Something
        },() ->{
            //do false Something
    });

转自: 大明哥_

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023年【公路水运工程施工企业安全生产管理人员】复审考试及公路水运工程施工企业安全生产管理人员考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 公路水运工程施工企业安全生产管理人员复审考试根据新公路水运工程施工企业安全生产管理人员考试大纲要求&#xff0c;安全生产模拟考试一点通将公路水运工程施工企业安全生产管理人员模拟考试试题进行汇编&#xff0…

人工智能-卷积神经网络(LeNet)

为了能够应用softmax回归和多层感知机&#xff0c;我们首先将每个大小为\(28\times28\)的图像展平为一个784维的固定长度的一维向量&#xff0c;然后用全连接层对其进行处理。 而现在&#xff0c;我们已经掌握了卷积层的处理方法&#xff0c;我们可以在图像中保留空间结构。 同…

学者观察 | 数字经济中长期发展中的区块链影响力——清华大学柴跃廷

导语 区块链是一种全新的分布式基础架构与计算范式&#xff0c;既能利用非对称加密和冗余分布存储实现信息不可篡改&#xff0c;又可以利用链式数据结构实现数据信息可溯源。当前&#xff0c;区块链技术已成为全球数据交易、金融结算、国际贸易、政务民生等领域的信息基础设施…

vue Sts认证后直传图片到阿里云OSS

后端进行sts认证生成临时身份凭证&#xff0c;前端通过凭证直传图片等文件到OSS中 一 OSS配置 增加用户和角色&#xff0c;创建OSS bucket 1.1 添加用户 登录阿里云管理控制台&#xff0c;右侧头像&#xff0c;进入访问控制 点击左侧导航栏的身份管理的用户&#xff0c;点击…

网络溯源-PSEXEC-简单

题干&#xff1a; 我们的入侵检测系统&#xff08;IDS&#xff09;已发出警报&#xff0c;指示涉及使用PsExec的可疑横向移动活动。为了有效响应此事件&#xff0c;您作为 SOC 分析师的角色是分析存储在 PCAP 文件中的捕获网络流量。 攻击者首次攻击成功的计算机源网络IP地址…

23款奔驰GLC260L升级香氛负离子 感受清香四溢

香氛负离子系统是由香氛系统和负离子发生器组成的一套配置&#xff0c;也可以单独加装香氛系统或者是负离子发生器&#xff0c;香氛的主要作用就是通过香氛外壳吸收原厂的香水再通过空调管输送到内饰中&#xff0c;而负离子的作用就是安装在空气管中通过释放电离子来打击空气中…

记录一次数据库内存占满

一&#xff0c;背景及表现 用户普遍反馈业务功能&#xff0c;无法加载出数据&#xff0c;服务挂了 二&#xff0c;数据库指标 三&#xff0c;排查方反馈 排查方反馈&#xff1a;查全量数据导致的&#xff0c;就是没查出来但是一直在查 四&#xff0c;分析 1.应用服务器问题…

ZYNQ通过AXI DMA实现PL发送连续大量数据到PS DDR

硬件&#xff1a;ZYNQ7100 软件&#xff1a;Vivado 2017.4、Xilinx SDK 2017.4   ZYNQ PL 和 PS 的通信方式有 AXI GPIO、BRAM、DDR等。对于数据量较少、地址不连续、长度规则的情况&#xff0c;BROM 比较适用。而对于传输速度要求高、数据量大、地址连续的情况&#xff0c;比…

facebook分享-错误记录

无法拉起分享 "code":30000,"msg":"fail:API_ERROR: API_ERROR" 1.确认facebook的app_id是否一致 2.确认是否在app_id应用的白名单里&#xff0c;注册meta开发者&#xff0c;然后把主页的user_id给管理员加 A ContentProvider for this app was…

dapp技术开发

随着区块链技术的普及和应用&#xff0c;DApp&#xff08;去中心化应用&#xff09;逐渐成为了区块链领域中备受关注的核心部分。DApp是一种运行在去中心化网络上的应用程序&#xff0c;其开发、部署和运行都不依赖于任何中心化的实体或中介机构。这种应用程序的兴起和发展&…

详解机器学习最优化算法

前言 对于几乎所有机器学习算法&#xff0c;无论是有监督学习、无监督学习&#xff0c;还是强化学习&#xff0c;最后一般都归结为求解最优化问题。因此&#xff0c;最优化方法在机器学习算法的推导与实现中占据中心地位。在这篇文章中&#xff0c;小编将对机器学习中所使用的…

赛宁网安入选国家工业信息安全漏洞库(CICSVD)2023年度技术组成员单

近日&#xff0c;由国家工业信息安全发展研究中心、工业信息安全产业发展联盟主办的“2023工业信息安全大会”在北京成功举行。 会上&#xff0c;国家工业信息安全发展研究中心对为国家工业信息安全漏洞库&#xff08;CICSVD&#xff09;提供技术支持的单位授牌表彰。北京赛宁…

Qt 自定义按钮 区分点按与长按信号,适配触摸事件

Qt 自定义按钮 区分点按与长按信号 适配触摸事件 效果 使用示例 // 点按connect(ui.btnLeft, &JogButton::stepclicked, this, &MainWindow::btnLeft_clicked);// 长按开始connect(ui.btnLeft, &JogButton::continueOn, this, &MainWindow::slotJogLeftOn);//…

通配符匹配

题目链接 通配符匹配 题目描述 注意点 s 仅由小写英文字母组成p 仅由小写英文字母、‘?’ 或 ‘*’ 组成‘?’ 可以匹配任何单个字符‘*’ 可以匹配任意字符序列&#xff08;包括空字符序列&#xff09; 解答思路 最初想到的是dfs 剪枝&#xff0c;但是用例超时了参照题…

React的refs和表单组件总结

React的refs和表单组件 react中refs的使用字符串形式的ref react核心就在于虚拟DOM&#xff0c;也就是React中不总是直接操页面的真实DOM元素&#xff0c;并且结合Diffing算法&#xff0c;可以做到最小化页面重绘&#xff0c;但有些时候不可避免我们需要一种方法可以操作我们定…

禅道项目信息通知到钉钉群配置步骤

禅道是我们常用的项目进度管理工具&#xff0c;禅道集成了webhook功能&#xff0c;可以通过发送 JSON 格式的数据到第三方hook地址&#xff0c;进行消息集成&#xff0c;包括钉钉、企业微信以及飞书。可以考虑将禅道和钉钉两者可以结合起来&#xff0c;将项目信息发送到钉钉群&…

SAP 10策略测试及简介

从今天开始将把PP模块中常用的一些策略进行一个测试,编写成系统的文档,有点策略经常不用自己都忘了一些策略的特性。所以还是有必须形成文档的形式记录下来 1、首先准备好物料 成品物料为AB0,在MRP3视图中维护对应的策略组的10 同时选择消耗模式为2.消耗期间都是999 2、其他…

软件安全测试怎么做?如何确保软件授权安全

在数字化不断演进的今天&#xff0c;软件安全测试变得至关重要。它验证了软件是否容易受到网络攻击&#xff0c;并检验恶意或意外输入对操作的影响。安全测试的目标是保障系统和信息的安全性和可靠性&#xff0c;确保它们不接受未授权的输入。 一、安全测试准备 开发者必须认识…

长安链可验证数据库,保证数据完整性的可信存证方案

近日&#xff0c;长安链发布“可验证数据库”实现了链上链下协同存储及数据完整性保证&#xff0c;显著提升长安链存储能力的可扩展性。 可信存证是联盟链最典型的应用场景&#xff0c;被广泛应用在司法、工业、农业、贸易等领域。联盟链的存证应用主要分为两个阶段&#xff1…