【问题标题】:Good practice to avoid code duplication Java避免代码重复的好习惯 Java
【发布时间】:2020-03-01 06:15:12
【问题描述】:

我有一个规范接口,我们称之为 Spec 和两个实现它的类,我们称之为 ImpAImpB。在我意识到 ImpAimpB 中的几个方法共享相同的实现之前,它一直很有效。 我试图通过在 Spec 中声明默认方法并在其中实现它们来避免它,但我确信有更好的方法来做到这一点。 也许一些设计模式?

【问题讨论】:

  • 创建一个只负责避免代码重复的新接口,而您的实际 Spec 类在没有任何默认方法的情况下处理基于业务逻辑的接口,怎么样?

标签: java design-patterns architecture software-design


【解决方案1】:

如果复制的代码不使用类的状态(实例变量),则将代码放在接口中的默认方法中是一种解决方案。

对于需要访问类实例变量的更复杂的情况,您可以使用通用代码创建一个额外的抽象类。然后ImpAImpB 将扩展抽象类。

Java 中的集合同时使用两者。例如,ArrayListLinkedList 扩展 AbstractList,它实现了 List,其中包含一些默认方法。

【讨论】:

  • 它使用来自其他类的列表,但我正在考虑在类中将它们设为静态,这样我就可以从接口访问它们,而不是创建一个新的抽象类。你怎么看?
  • 很难说没有更多信息 - 使用静态对象在类之间进行通信通常会使您的代码更难测试并且更脆弱。但这真的取决于细节。
  • 我要完成单独的规范和实现,这是这个项目的主要任务。
  • 如果接口还定义了状态的访问器,您可以在接口中使用默认方法来访问状态。如果所述状态是不应该发布的内部废话,当然是不可取的。
【解决方案2】:

虽然您可以按照您的建议将它们设为default 方法,但另一个可能的解决方案是使用Delegation 设计模式。这意味着有第四个类,完全是为了分离公共逻辑。如果该逻辑需要值来操作,则应将它们注入到委托中以允许其独立操作(和测试)。

就个人而言,我发现更喜欢委托而不是组合的代码更优雅、更可测试且更“可重构”。但是,与许多其他设计问题一样,对此有许多不同且有效的意见。

interface Spec { 
    void method();
}

class Imp1 implements Spec {
    private final Delegate delegate;

    public Imp1() {
        this.delegate = new Delegate(...);
    }

    public void method() {
        delegate.setContext(...);
        delegate.method();
    }
}

【讨论】:

    【解决方案3】:

    您可以将 Spec 设为超类,并将 ImpA 和 ImpB 设为子类。您可以找到更多信息on the JavaDoc

    【讨论】:

    • 鉴于 Spec 是一个接口,它确实不应该转换为超类。接口有一个非常特定的用途。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 2014-03-07
    • 2015-05-01
    • 1970-01-01
    • 2011-07-13
    相关资源
    最近更新 更多