slot deposit pulsa slot mahjong slot gacor slot gacor slot gacor resmi slot gacor 2025 slot gacor terpercaya slot gacor 2025 slot gacor hari ini slot gacor hari ini slot gacor hari ini
请停止在 Java 中使用 if-else 语句
17611538698
webmaster@21cto.com

请停止在 Java 中使用 if-else 语句

编程语言 0 1003 2024-09-05 06:27:02

图片

导读:


反 IF 编程方法由 Francesco Cirillo 于 2007 年发起,它改变了许多人对软件设计中的 IF 和条件句的看法。


软件设计的核心是一种简单但潜在危险的工具:条件“IF”语句。不可否认,它的基础性在于,它用于处理增长环境中的变化,被称为“IF 策略”,它可能是一个无声的破坏者,使代码复杂化和逻辑混乱。


IF 策略可能导致调试问题、从未交付的用户故事、技术债务、纠结的设计、团队中的摩擦和其他低效率。


从本质上讲,IF 策略会增加成本并延迟软件交付时间,同时降低内部质量。

有一个传说中古老的遗留系统,我的同事从上到下编码了数千行,每个块都添加了几个 if then java 部分来做路由,我感觉自己被困在一个陌生的仙境中。

在这篇文章中,我将向大家展示如何优化 if-else 的使用,限制具有太多分支条件的代码,并使我们的 Java 代码更易于阅读和理解。

代码片段包含太多 if-else 语句


在深入研究优化细节之前,让我们使用一个包含多个 if else 条件的示例演示 Java 代码,然后以各种方式对其进行优化:


public class ShippingCostCalculator {    public double calculateShippingCost(String shippingType, double weight) {        if (shippingType.equals("STANDARD")) {            return weight * 5.0;        } else if (shippingType.equals("EXPRESS")) {            return weight * 10.0;        } else if (shippingType.equals("SAME_DAY")) {            return weight * 20.0;        } else if (shippingType.equals("INTERNATIONAL")) {            return weight * 50.0;        } else if (shippingType.equals("OVERNIGHT")) {            return weight * 30.0;        }        return 0;    }}


如各位所见,上面的代码功能是根据快递类型计算运费。

使用枚举进行优化


现在,我们将使用Enum来替换语句if-else:


public enum ShippingType {    STANDARD {        @Override        public double getCost(double weight) {            return weight * 5.0;        }    },    EXPRESS {        @Override        public double getCost(double weight) {            return weight * 10.0;        }    },    SAME_DAY {        @Override        public double getCost(double weight) {            return weight * 20.0;        }    },    INTERNATIONAL {        @Override        public double getCost(double weight) {            return weight * 50.0;        }    },    OVERNIGHT {        @Override        public double getCost(double weight) {            return weight * 30.0;        }    };
public abstract double getCost(double weight);}


public class ShippingCostCalculator {
public double calculateShippingCost(ShippingType shippingType, double weight) { return shippingType.getCost(weight); }}


public class MainCost {    public static void main(String[] args) {        var calculator = new ShippingCostCalculator();        var cost = calculator.calculateShippingCost(ShippingType.EXPRESS, 2.5);        System.out.println("Shipping cost: " + cost);    }}


可以看到,复杂的 if-else 语句被简化成了两行简短、直接的代码。运行 main 函数,查看结果。

图片


优势:

  • 可扩展性:添加新的运输类型和值。枚举并定义处理方法。

  • 可维护且可理解的代码:每种传输方法的原因都是独立的且易于理解。


然而,使用Enum也有一些明显的缺点,您应该考虑:

  • 可扩展性:添加新的运输类型和值。枚举并定义处理方法。

  • 难以添加新参数:当需要更多参数时,Enum 不太适合,并且代码变得繁琐。

  • 继承限制:Enum不能从其他类继承,这降低了它们重用逻辑的潜力。


使用 Enum 进行优化通常适用于参数较少的简单情况。

使用工厂模式进行优化


还是上面乱七八糟的代码,我们按照如下方式进行优化:

创建接口 ShippingCostStrategy

public interface ShippingCostStrategy {    double calculate(double weight);}

现在我们将创建一个工厂类来处理基于运输类型的策略路由:

import java.util.HashMap;import java.util.Map;
public class ShippingCostFactory { private static final Map strategies = new HashMap<>();
static { strategies.put("STANDARD", new StandardShipping()); strategies.put("EXPRESS", new ExpressShipping()); strategies.put("SAME_DAY", new SameDayShipping()); strategies.put("INTERNATIONAL", new InternationalShipping()); strategies.put("OVERNIGHT", new OvernightShipping()); }
public static ShippingCostStrategy getStrategy(String shippingType) { ShippingCostStrategy strategy = strategies.get(shippingType); if (strategy == null) { throw new IllegalArgumentException("Invalid shipping type: " + shippingType); } return strategy; }}

现在只需调用并使用它。

public class ShippingCostCalculator {    public double calculateShippingCost(String shippingType, double weight) {        ShippingCostStrategy strategy = ShippingCostFactory.getStrategy(shippingType);        return strategy.calculate(weight);    }}


工厂模式的优点:

  • 易于扩展:只需开发附加类并更新工厂即可添加新的交付类型,而无需更改核心代码。

  • 逻辑分离:收费逻辑是独立的,易于管理和维护。

  • 灵活性:工厂可能会根据其他因素返回多个解决方案,从而提高灵活性。


使用策略模式进行优化


在我们详细讨论之前,请记住,实现方式与工厂类似,但使用目的略有不同:

public interface ShippingCostStrategy {    double calculate(double weight);}


public class StandardShipping implements ShippingCostStrategy {    @Override    public double calculate(double weight) {        return weight * 5.0;    }}
public class ExpressShipping implements ShippingCostStrategy { @Override public double calculate(double weight) { return weight * 10.0; }}
public class SameDayShipping implements ShippingCostStrategy { @Override public double calculate(double weight) { return weight * 20.0; }}
public class InternationalShipping implements ShippingCostStrategy { @Override public double calculate(double weight) { return weight * 50.0; }}
public class OvernightShipping implements ShippingCostStrategy { @Override public double calculate(double weight) { return weight * 30.0; }}

现在我们将创建 ShippingContext 来管理策略。

public class ShippingCostContext {    private ShippingCostStrategy strategy;
public void setStrategy(ShippingCostStrategy strategy) { this.strategy = strategy; }
public double calculateShippingCost(double weight) { return strategy.calculate(weight); }}
import java.util.HashMap;import java.util.Map;
public class ShippingCostCalculator {
private static final Map strategies = new HashMap<>();
static { strategies.put("STANDARD", new StandardShipping()); strategies.put("EXPRESS", new ExpressShipping()); strategies.put("SAME_DAY", new SameDayShipping()); strategies.put("INTERNATIONAL", new InternationalShipping()); strategies.put("OVERNIGHT", new OvernightShipping()); }
private final ShippingCostContext context = new ShippingCostContext();
public double calculateShippingCost(String shippingType, double weight) { ShippingCostStrategy strategy = strategies.get(shippingType); if (strategy == null) { throw new IllegalArgumentException("Invalid shipping type: " + shippingType); } context.setStrategy(strategy); return context.calculateShippingCost(weight); }}


现在,把它放进主类里面使用。

public class MainCost {
public static void main(String[] args) ShippingCostCalculator calculator = new ShippingCostCalculator();
double weight = 10.0;
String shippingType1 = "STANDARD"; double cost1 = calculator.calculateShippingCost(shippingType1, weight); System.out.println("Shipping cost for " + shippingType1 + ": " + cost1);
String shippingType2 = "EXPRESS"; double cost2 = calculator.calculateShippingCost(shippingType2, weight); System.out.println("Shipping cost for " + shippingType2 + ": " + cost2);
String shippingType3 = "SAME_DAY"; double cost3 = calculator.calculateShippingCost(shippingType3, weight); System.out.println("Shipping cost for " + shippingType3 + ": " + cost3);
String shippingType4 = "INTERNATIONAL"; double cost4 = calculator.calculateShippingCost(shippingType4, weight); System.out.println("Shipping cost for " + shippingType4 + ": " + cost4);
String shippingType5 = "OVERNIGHT"; double cost5 = calculator.calculateShippingCost(shippingType5, weight); System.out.println("Shipping cost for " + shippingType5 + ": " + cost5); }
}

图片


在前两种情况下,策略模式管理如何计算运输成本,而工厂模式根据运输类型决定采用哪种策略。

使用 Stream API 和 Map 进行优化


import java.util.HashMap;import java.util.Map;
public class ShippingCostCalculator {
private static final Map shippingCosts = new HashMap<>();
static { shippingCosts.put("STANDARD", 5.0); shippingCosts.put("EXPRESS", 10.0); shippingCosts.put("SAME_DAY", 20.0); shippingCosts.put("INTERNATIONAL", 50.0); shippingCosts.put("OVERNIGHT", 30.0); }
public double calculateShippingCost(String shippingType, double weight) { return shippingCosts.entrySet().stream() .filter(entry -> entry.getKey().equalsIgnoreCase(shippingType)) .map(Map.Entry::getValue) .findFirst() .orElse(0.0) * weight; }
public static void main(String[] args) { ShippingCostCalculator calculator = new ShippingCostCalculator();
double weight = 10.0;
String shippingType1 = "STANDARD"; double cost1 = calculator.calculateShippingCost(shippingType1, weight); System.out.println("Shipping cost for " + shippingType1 + ": " + cost1);
String shippingType2 = "EXPRESS"; double cost2 = calculator.calculateShippingCost(shippingType2, weight); System.out.println("Shipping cost for " + shippingType2 + ": " + cost2);
String shippingType3 = "SAME_DAY"; double cost3 = calculator.calculateShippingCost(shippingType3, weight); System.out.println("Shipping cost for " + shippingType3 + ": " + cost3);
String shippingType4 = "INTERNATIONAL"; double cost4 = calculator.calculateShippingCost(shippingType4, weight); System.out.println("Shipping cost for " + shippingType4 + ": " + cost4);
String shippingType5 = "OVERNIGHT"; double cost5 = calculator.calculateShippingCost(shippingType5, weight); System.out.println("Shipping cost for " + shippingType5 + ": " + cost5);
String invalidType = "INVALID"; double invalidCost = calculator.calculateShippingCost(invalidType, weight); System.out.println("Shipping cost for " + invalidType + ": " + invalidCost); }}


图片

这个策略也比较方便,虽然扩展性不如Factory和Strategy,但对于简单的场景来说还是一个可行的选择。

谢谢大家,在您离开之前:

👏 请为文章点赞或转发 👉
也欢迎在下面的评论部分分享您的问题或见解。

本文最初于 2024 年 8 月 20 日发布于https://cafeincode.com

作者:陈兴

评论