整洁代码开发--重构技巧

97 阅读4分钟

重构技巧

1. 重构方法

1.1 使用新语法

  • 函数式接口和Lambda表达式 函数式接口是指有且仅有一个抽象方法的接口。 Lambda表达式使得代码更加简洁和表达性更强,特别是在处理集合操作、事件处理等场景中非常有用。
@FunctionalInterface
public interface AddOperation {
    int add(int a, int b);
}
// 自定义Lambda表达式实现加法操作
AddOperation addOperation = (a, b) -> a + b;

// 调用Lambda表达式计算两数之和
int result = addOperation.add(5, 3);
System.out.println("The sum of 5 and 3 is: " + result);

// 进一步演示,使用Lambda直接在方法调用中
int directSum = calculateSumUsingLambda(7, 9, (x, y) -> x + y);
System.out.println("The direct sum of 7 and 9 is: " + directSum);
// 一个接受Lambda作为参数的方法
public static int calculateSumUsingLambda(int x, int y, AddOperation operation) {
    return operation.add(x, y);
}
  • stream
public static void main(String[] args) {
    List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
    List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

    List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
    // 获取空字符串的数量
    int count = (int) strings.parallelStream().filter(string -> string.isEmpty()).count();

}

2.设计模式

在Java编程中,设计模式的多样性为软件开发提供了丰富的解决方案。恰当地应用这些设计模式,不仅能提升代码的整洁度,还能增强代码的美感和可维护性。

列举两个工作中频繁遇见的情景进行代码重构的实例。

2.1 巧用适配器模式提高系统的可扩展性

适配器模式是一种结构型设计模式,它允许将不兼容的接口转换为客户端期望的接口,从而使原本不兼容的类能够协同工作。在软件开发中,巧用适配器模式可以显著提高系统的可扩展性和灵活性,尤其是在处理遗留系统集成、第三方API接入或是应对需求变更等方面。 下面通过一个具体例子来说明如何利用适配器模式提升系统的可扩展性:

  • 场景描述

假设你正在开发一个电商平台,该平台最初设计时支持从内部数据库获取商品信息。 现在业务扩展,需要从多个供应商那里获取商品数据,但这些供应商提供的API接口各不相同,直接集成会导致代码复杂度剧增且难以维护。

  • 未使用适配器模式前

如果不使用适配器模式,你可能需要为每一个供应商编写特定的处理逻辑,代码将会充斥着大量的条件分支或if-else语句,这不仅使得代码难以阅读和维护, 而且每当新增一个供应商时,都需要修改核心业务逻辑代码,违反了开放封闭原则。

  • 应用适配器模式实现

定义目标接口: 首先,定义一个统一的商品信息接口ProductInfo,该接口声明了获取商品信息所需的所有方法,比如getName(), getPrice(), getDescription()等。

public interface ProductInfo {
    String getName();
    double getPrice();
    String getDescription();
}

创建适配器接口及实现:为每个供应商API创建一个适配器接口和实现,这些适配器需要将供应商的特定接口转换为目标接口ProductInfo

public interface SupplierAdapter {
    ProductInfo adapt(ProductApi apiResponse);
}

public class SupplierAAdapter implements SupplierAdapter {
    @Override
    public ProductInfo adapt(ProductApi apiResponse) {
        // 将Supplier A的apiResponse转换为ProductInfo对象
        return new ProductInfoImpl(apiResponse.getName(), apiResponse.getPrice(), apiResponse.getDescription());
    }
}

// 以此类推,为其他供应商创建适配器...

核心业务逻辑:在电商平台的核心业务逻辑中,只需要使用ProductInfo接口,无需关心数据来源的具体实现。当需要支持新的供应商时,只需添加对应的适配器类,无需修改现有业务逻辑。

public class ProductService {
    private List<SupplierAdapter> adapters;

    public ProductService(List<SupplierAdapter> adapters) {
        this.adapters = adapters;
    }

    public List<ProductInfo> fetchProductsFromSuppliers() {
        List<ProductInfo> products = new ArrayList<>();
        for (SupplierAdapter adapter : adapters) {
            // 假设从某个供应商API获取数据
            ProductApi apiResponse = getApiResponseFromSupplier(adapter);
            ProductInfo product = adapter.adapt(apiResponse);
            products.add(product);
        }
        return products;
    }

    // 假设的模拟方法,实际中应替换为调用供应商API
    private ProductApi getApiResponseFromSupplier(SupplierAdapter adapter) {
        // 实现逻辑...
    }
}

通过引入适配器模式,系统能够在不修改原有业务逻辑的基础上,灵活地增加对新供应商的支持。这不仅降低了系统的耦合度,提高了代码的可读性和可维护性,同时也大大增强了系统的可扩展性,使之能更轻松地适应未来的需求变化。

2.2 使用策略模式避免冗长的if-else/switch分支

bad case:

public class OrderService {
        public double discount(Order order) {
            double discount = 0.0;
            OrderType type = order.getType();
            if (type.equals(OrderType.NORMAL)) { // 普通订单
                //...省略折扣计算算法代码
            } else if (type.equals(OrderType.GROUPON)) { // 团购订单
                //...省略折扣计算算法代码
            } else if (type.equals(OrderType.PROMOTION)) { // 促销订单
                //...省略折扣计算算法代码
            }
            return discount;
        }
    }

使用策略模式避免冗长的if-else/switch分支:将不同类型订单的打折策略设计成策略类,并由工厂类来负责创建策略对象。

// 定义策略接口
public interface DiscountStrategy {
    double calDiscount(Order order);
}

// 具体策略实现
// 省略NormalDiscountStrategy、GrouponDiscountStrategy、PromotionDiscountStrategy类代码...

// 建立策略工厂
public class DiscountStrategyFactory {
    private static final Map<OrderType, DiscountStrategy> strategies = new HashMap<>();

    static {
        strategies.put(OrderType.NORMAL, new NormalDiscountStrategy());
        strategies.put(OrderType.GROUPON, new GrouponDiscountStrategy());
        strategies.put(OrderType.PROMOTION, new PromotionDiscountStrategy());
    }

    public static DiscountStrategy getDiscountStrategy(OrderType type) {
        return strategies.get(type);
    }
}

// 策略的使用
public class OrderService {
    public double discount(Order order) {
        OrderType type = order.getType();
        DiscountStrategy discountStrategy = DiscountStrategyFactory.getDiscountStrategy(type);
        return discountStrategy.calDiscount(order);
    }
}