【问题标题】:Code duplication (or not) - JAVA代码重复(或不重复) - JAVA
【发布时间】:2012-08-15 08:56:33
【问题描述】:

我有代码重复的情况(或者是吗?),我不知道如何避免它,但我的代码仍然保持清晰。

让我把情况大大简化:

// let's say I have a interface Entity

interface Entity {

    public Entity add (Entity operand);

}

// And two classes that implement this interface

class MyInteger implements Entity {

    private int value;

    public Entity add (Entity operand)
    {
         // here I have to manage the situation distinctly if operand is a MyInteger or MyString

    }

}

class MyString implements Entity {

    private String value;

    public Entity add (Entity operand )
    {

    }
}

现在,我的问题是 MyString 中的 add 方法与 MyInteger 中的 add 方法基本相同。请记住,我有比这里提到的两种类型更多的类型,并且对于某些方法 add 是不一样的。

这是代码重复吗?如果是这样,有没有办法避免它?因为我似乎想不出一个。

另外,在 add 方法中,如何在不使用 if (instanceof) 语句的情况下切换操作数的各种类型?

【问题讨论】:

    标签: java interface instanceof code-duplication


    【解决方案1】:

    您可以使用抽象类并为其提供具体的 add 方法。

    【讨论】:

    • 我不确定我是否遵循。没有具体的添加方法。结果因操作数而异。假设我添加了两个 MyInteger,我的结果也是一个 MyInteger,但是如果我将一个 MyInteger 添加到一个 MyString,则结果是一个 MyString。你能给我一个代码示例来说明你的意思吗?
    【解决方案2】:

    听起来您需要visitordouble-dispatch 机制。

    您的add(Entity operand) 方法必须根据传递的操作数来决定要做什么,因此您可以通过在操作数上调用back 来实现这一点。例如

    // in MyInteger
    public Entity add(Entity operand) {
       operand.addInteger(this);
    }
    
    // in MyString
    public Entity add(Entity operand) {
       operand.addString(this);
    }
    

    请注意,上述实现会根据所调用的类型而改变。通过重定向回操作数,您的调用路径由最初调用的实体使用的操作数确定。

    每个实体都必须实现addInteger(MyInteger p)addString(MyString p) 等,但在这个阶段,您可以使用具体的类型,并且可以轻松地确定要做什么。

    请注意,您不必使用 instanceof 或类似名称。以上是类型安全且完整的。例如添加新的操作数类型将导致一组明显的重构。

    【讨论】:

    • 这是一种很好的回调方式。我不清楚这是如何取代“instanceof”的。如果我错了,请纠正我,但这里的想法是让实体类型处理细节?
    • 如果您添加 MyDouble ,那么它将在操作符上调用 addDouble 。每个操作者都必须决定如何向自己添加一个双精度(不是不合理的)
    • 我认为这没有帮助。 Entity 是一个接口,因此在 Entity 中实现之前,您不能将 addInteger/addString 作为方法调用。正如其他答案所说,您需要一个抽象超类或实用方法。
    • 感谢您的回答,非常有帮助。
    • 我也不明白。这意味着实体必须了解未来所​​有可能的“子类”,并拥有 addCat()、addDog() 方法等。
    【解决方案3】:

    到目前为止,我没有发现您的方法存在问题。

    由于实体是一个实例,您可以通过以下方式解决代码重复:

    • 只需忽略它并进行复制,因为它会给你一个干净的解决方案。 如果您只有少数情况会发生此类重复,则最好 以这种方式实现它。

    • 如前所述,实现一个抽象类,例如AbstractEntity 实现所有 方法一次作为受保护的成员方法,并将 MyInteger 和 MyString 声明为子类。

    • 进一步进行子类化,考虑哪个实体需要哪些方法,以及 建立一个子类树。注意:这将妨碍进一步的调整,如果您 不能做仔细的设计。

    • 使用实用程序类:具有公共静态方法和私有构造函数的类 实现所需的功能。

    如何找出实体的类型:

    • 使用 instanceof(好吧,它很丑)
    • 在返回类型为 Enum 或 test 的接口中实现方法 对于属性:getType() == STRING 或 isString()
    • 按照您的意愿在接口中实现方法:checkIfStringAndAddIt()。

    【讨论】:

      【解决方案4】:

      查找模板模式。您可以为任何重复的代码重构并添加一个 Abstract 类。如果这特定于两个类,您可以只让这两个类扩展 Abstract 类。

      为了避免instanceof,我不确定什么是最好的,但您可以链接一个特定于实体类的额外方法,然后在必要时调用超级/抽象类。

      最后,研究泛型提供了哪些可能性。

      【讨论】:

        猜你喜欢
        • 2012-01-13
        • 1970-01-01
        • 1970-01-01
        • 2023-03-29
        • 2012-10-30
        • 2012-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多