3

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

让我把情况大大简化:

// 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) 语句的情况下在操作数的各种类型之间进行切换?

4

4 回答 4

1

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

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

最后,调查泛型提供了哪些可能性。

于 2012-08-15T08:59:10.690 回答
1

听起来您需要访问者双重调度机制。

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

// 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或类似。以上是类型安全且完整的。例如,添加一个新的操作数类型将导致一组明显的重构。

于 2012-08-15T08:59:13.080 回答
1

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

于 2012-08-15T08:59:35.717 回答
1

到目前为止,我认为您的方法没有问题。

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

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

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

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

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

如何找出实体的类型:

  • 使用 instanceof(好吧,这很丑)
  • 在接口中实现方法返回类型为 Enum 或测试属性:getType() == STRING 或 isString()
  • 在接口中实现您希望的方法:checkIfStringAndAddIt()。
于 2012-08-15T10:56:12.430 回答