简体   繁体   English

代码重复(或不重复) - JAVA

[英]Code duplication (or not) - JAVA

I have a situation of code duplication (or is it ? ) and I don't know how to avoid it , but still keep clarity in my code. 我有一个代码重复的情况(或者是吗?),我不知道如何避免它,但仍然保持我的代码清晰。

Let me hugely oversimplify the situation: 让我大大简化一下情况:

// 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 )
    {

    }
}

Now, my problem is that the method add in MyString is bassicly the same as the method add in MyInteger. 现在,我的问题是,在MyString中添加的方法与MyInteger中添加的方法相同。 Keep in mind that I have way more types than the two mentioned here, and for some the method add is not the same. 请记住,我有比这里提到的更多的类型,并且对于一些方法添加是不一样的。

Is this code duplication? 这段代码是否重复? And if so, is there a way to avoid it? 如果是这样,有没有办法避免它? Cause I can't seem to think of one. 因为我似乎无法想到一个。

Also , in the add method, how can I switch between the various types operand can have without using if (instanceof ) statements? 另外,在add方法中,如何在不使用if(instanceof)语句的情况下切换各种类型的操作数?

Look up the Template pattern. 查找模板模式。 You could refactor and add an Abstract class for any duplicate code. 您可以重构并为任何重复的代码添加Abstract类。 If this is specific to two classes you could have just those two classes extend the Abstract class. 如果这是特定于两个类的,那么您可以只使用这两个类来扩展Abstract类。

To avoid instanceof I'm not sure what would be best but you could chain an extra method specific to an entity class which then calls the super/abstract class if necessary. 为了避免instanceof我不确定什么是最好的,但你可以链接一个特定于实体类的额外方法,然后在必要时调用super / abstract类。

Lastly, investigate what possibilities are offered by generics. 最后,研究仿制药提供的可能性。

Sounds like you need the visitor or double-dispatch mechanism. 听起来你需要访问者双重调度机制。

Your add(Entity operand) method has to decide what to do based on the operand passed, and so you can achive this by calling back on the operand. 你的add(Entity operand)方法必须根据传递的操作数决定做什么,所以你可以通过回调操作数来实现这一点。 eg 例如

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

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

Note that the implementation of the above changes upon the type called. 请注意,上述实现在所调用的类型上发生了变化。 By redirecting back to the operand your call path is determined by the entity originally called upon and the operand used. 通过重定向回操作数,您的调用路径由最初调用的实体和使用的操作数确定。

Each Entity would have to implement addInteger(MyInteger p) , addString(MyString p) etc. but at this stage you have concrete types to work with and can determine trivially what to do. 每个实体都必须实现addInteger(MyInteger p)addString(MyString p)等,但是在这个阶段你可以使用具体的类型,并且可以很容易地确定要做什么。

Note that you're not having to use instanceof or similar. 请注意,您不必使用instanceof或类似的。 The above is typesafe and complete. 以上是类型安全和完整的。 eg adding a new operand type will result in an obvious set of refactorings. 例如,添加新的操作数类型将导致一组明显的重构。

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

So far I do not see problems in your approach. 到目前为止,我没有看到你的方法存在问题。

As entity is an instance, you can solve code duplication by: 由于实体是一个实例,您可以通过以下方式解决代码重复问题:

  • Simply ignoring it and do duplication because it will give you a clean solution. 简单地忽略它并重复,因为它会给你一个干净的解决方案。 If you have only a few cases where such duplication occur, it may be better to implement it in this way. 如果只有少数情况发生这种重复,以这种方式实现它可能会更好。

  • As already said, implement an abstract class eg AbstractEntity implementing all methods once as protected member methods and declare MyInteger and MyString as subclasses. 如前所述,实现一个抽象类,例如AbstractEntity,将所有方法实现为受保护的成员方法,并将MyInteger和MyString声明为子类。

  • Go further with subclassing, think over what methods are needed for which entity and build up a tree of subclasses. 进一步了解子类化,思考哪个实体需要哪些方法,并构建子类树。 Caution: This will hamper further adjustments if you cannot do careful design. 注意:如果您不能仔细设计,这将妨碍进一步的调整。

  • Use an utility class: class with public static methods and a private constructor to implement the functionality to need. 使用实用程序类:具有公共静态方法的类和私有构造函数来实现所需的功能。

How to find out the type of entity: 如何找出实体的类型:

  • Use instanceof (ok, it IS ugly) 使用instanceof(好吧,它很难看)
  • Implement methods in the interface returning the type as Enum or test for properties: getType() == STRING or isString() 在接口中实现方法,将类型返回为Enum或测试属性:getType()== STRING或isString()
  • Implement methods in the interface doing what you wish: checkIfStringAndAddIt(). 在接口中实现您想要的方法:checkIfStringAndAddIt()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM