Java代码重构:提取通用方法消除重复代码

本文旨在讲解如何通过提取通用方法来消除Java代码中的重复逻辑。针对类型不同的数据,我们将探讨使用泛型方法和非泛型方法两种方式来实现代码的复用,从而提高代码的可维护性和可读性。通过具体的代码示例,我们将一步步演示如何进行重构,并提供相应的注意事项,帮助开发者更好地掌握这项技巧。

在软件开发过程中,代码重复是一个常见的问题,它会导致代码冗余、维护困难,并且增加出错的风险。为了解决这个问题,我们可以采用重构的手段,将重复的代码提取成通用的方法,从而提高代码的复用性和可维护性。本文将以一个具体的示例,讲解如何在Java中提取通用方法,消除重复代码。

示例场景

假设我们有一个Builder类,用于构建对象,其中有两个方法withUnit和withTime,它们的代码逻辑非常相似,都用于向列表中添加元素,并且都包含非空判断。

import java.util.ArrayList;
import java.util.List;

interface UnitIf {}
interface TimeIf {}

class Builder {
    private final List

unit = new ArrayList<>(); private final List time = new ArrayList<>(); public Builder withUnit(final UnitIf aUnit) { //Extract to method if (aUnit != null) { unit.add(aUnit); } return this; //---------------- } public Builder withTime(final TimeIf aTime) { //Extract to method if (aTime != null) { time.add(aTime); } return this; //---------------- } }

可以看到,withUnit和withTime方法中的if (aUnit != null)和if (aTime != null)以及unit.add(aUnit)和time.add(aTime)部分是重复的。接下来,我们将通过提取通用方法来消除这些重复代码。

使用泛型方法提取通用逻辑

为了处理不同类型的数据,我们可以使用泛型方法。下面是一个泛型方法的示例,它可以接受任何类型的列表和对象,并在对象非空时将其添加到列表中。

public  Builder addIfNonNull(List dst, T x) {
    if (x != null) {
        dst.add(x);
    }
    return this;
}

在这个方法中,表示这是一个泛型方法,T表示类型参数,List表示列表的类型是T,T x表示参数x的类型是T。

有了这个通用方法,我们就可以重构withUnit和withTime方法了:

public Builder withUnit(final UnitIf aUnit) {
    return addIfNonNull(unit, aUnit);
}

public Builder withTime(final TimeIf aTime) {
    return addIfNonNull(time, aTime);
}

可以看到,重构后的代码更加简洁,可读性也更高。

完整代码示例

import java.util.ArrayList;
import java.util.List;

interface UnitIf {}
interface TimeIf {}

class Builder {
    private final List unit = new ArrayList<>();
    private final List time = new ArrayList<>();

    public  Builder addIfNonNull(List dst, T x) {
        if (x != null) {
            dst.add(x);
        }
        return this;
    }

    public Builder withUnit(final UnitIf aUnit) {
        return addIfNonNull(unit, aUnit);
    }

    public Builder withTime(final TimeIf aTime) {
        return addIfNonNull(time, aTime);
    }
}

使用非泛型方法提取通用逻辑

如果不希望使用泛型方法,也可以使用非泛型方法,将参数类型设置为Object。

public Builder addIfNonNull(List dst, Object x) {
    if (x != null) {
        dst.add(x);
    }
    return this;
}

需要注意的是,在使用非泛型方法时,编译器会发出警告,因为List没有指定类型。虽然Java编译器会将List编译成List,这个过程被称为“类型擦除”,但在实际开发中,建议尽量使用泛型方法,以提高代码的类型安全性。

注意事项

  • 在提取通用方法时,需要仔细分析代码,确保提取的逻辑是真正通用的,并且不会引入新的问题。
  • 在使用泛型方法时,需要注意类型参数的命名,尽量使用有意义的名称,以提高代码的可读性。
  • 在使用非泛型方法时,需要注意类型转换的问题,避免出现类型转换异常。

总结

通过提取通用方法,我们可以有效地消除代码中的重复逻辑,提高代码的复用性和可维护性。在实际开发中,应该根据具体情况选择合适的提取方式,并注意相关的注意事项,从而编写出更加高质量的代码。