告别if-else逻辑分支,让编程更优雅

在开发过程中,我们常常会遇到遗留系统中充斥着大量 if-else 语句的代码。这些代码不仅难以维护,还容易引入错误。本文将介绍如何通过多种方式优化 if-else 的使用,使代码更具可读性、可维护性和扩展性。


原始代码:包含过多 if-else 语句的示例

以下是一个典型的 if-else 代码片段,用于根据运输类型计算运费:

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

问题分析 

  • 可读性差

    :过多的 if-else 语句使代码难以阅读。

  • 难以扩展

    :添加新的运输类型需要修改核心逻辑。

  • 容易出错

    :字符串比较容易拼写错误,且缺乏类型安全性。


优化方案 1:使用枚举(Enum)替换 if-else

枚举是一种类型安全的方式,可以有效地替代 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);
    }
}

优势 

  • 类型安全

    :避免字符串比较错误。

  • 可扩展性

    :添加新的运输类型只需扩展枚举。

  • 代码清晰

    :每种运输类型的逻辑独立且易于理解。

缺点 

  • 不适合复杂场景

    :如果需要添加更多参数,枚举会变得繁琐。

  • 继承限制

    :枚举不能继承其他类,限制了代码复用。


优化方案 2:使用工厂模式

工厂模式通过将对象的创建与使用分离,进一步优化代码结构。

运费策略接口 

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

具体策略实现 

public class StandardShipping implements ShippingCostStrategy {
    @Override
    public double calculate(double weight) {
        return weight * 5.0;
    }
}

publicclass ExpressShipping implements ShippingCostStrategy {
    @Override
    public double calculate(double weight) {
        return weight * 10.0;
    }
}

publicclass SameDayShipping implements ShippingCostStrategy {
    @Override
    public double calculate(double weight) {
        return weight * 20.0;
    }
}

publicclass InternationalShipping implements ShippingCostStrategy {
    @Override
    public double calculate(double weight) {
        return weight * 50.0;
    }
}

publicclass OvernightShipping implements ShippingCostStrategy {
    @Override
    public double calculate(double weight) {
        return weight * 30.0;
    }
}

工厂类 

import java.util.HashMap;
import java.util.Map;

publicclass ShippingCostFactory {
    privatestaticfinal 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) {
            thrownew 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);
    }
}

优势 

  • 易于扩展

    :添加新的运输类型只需创建新的策略类并更新工厂。

  • 逻辑分离

    :每种运输类型的逻辑独立,易于维护。

  • 灵活性

    :工厂可以根据需要返回不同的策略。


优化方案 3:使用策略模式

策略模式与工厂模式类似,但更侧重于动态切换算法。

运费策略接口 

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

具体策略实现 

public class StandardShipping implements ShippingCostStrategy {
    @Override
    public double calculate(double weight) {
        return weight * 5.0;
    }
}

publicclass ExpressShipping implements ShippingCostStrategy {
    @Override
    public double calculate(double weight) {
        return weight * 10.0;
    }
}

publicclass SameDayShipping implements ShippingCostStrategy {
    @Override
    public double calculate(double weight) {
        return weight * 20.0;
    }
}

publicclass InternationalShipping implements ShippingCostStrategy {
    @Override
    public double calculate(double weight) {
        return weight * 50.0;
    }
}

publicclass OvernightShipping implements ShippingCostStrategy {
    @Override
    public double calculate(double weight) {
        return weight * 30.0;
    }
}

上下文类 

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;

publicclass ShippingCostCalculator {

    privatestaticfinal 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());
    }

    privatefinal ShippingCostContext context = new ShippingCostContext();

    public double calculateShippingCost(String shippingType, double weight) {
        ShippingCostStrategy strategy = strategies.get(shippingType);
        if (strategy == null) {
            thrownew 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);
    }
}

优势 

  • 动态切换策略

    :可以在运行时动态切换不同的计算策略。

  • 逻辑分离

    :每种策略的实现独立,易于维护和扩展。


优化方案 4:使用 Stream API 和 Map

对于简单的场景,可以使用 Java 8 的 Stream API 和 Map 来优化代码。

import java.util.HashMap;
import java.util.Map;

publicclass ShippingCostCalculator {

    privatestaticfinal 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);
    }
}

优势 

  • 简洁性

    :代码简洁,适合简单场景。

  • 易于实现

    :无需定义额外的类或接口。

缺点 

  • 扩展性差

    :不适合复杂的业务逻辑。


总结

通过枚举、工厂模式、策略模式和 Stream API,我们可以有效地优化 if-else 语句,使代码更具可读性、可维护性和扩展性。选择哪种优化方式取决于具体的业务场景和需求。


你可能感兴趣的:(java,android,开发语言)