Java 如果无法更改接口,如何重构此方法?

Java 如果无法更改接口,如何重构此方法?,java,refactoring,findbugs,pmd,Java,Refactoring,Findbugs,Pmd,如果无法修改事件接口,如何重构以下方法?PMD报告太复杂,findbugs报告ITC_继承_类型_检查。还有魔法数字,如3、4、5等等 public int getEventCode(Event event) { if (event instanceof OneEvent) { return 1; } if (event instanceof TwoEvent) { return 2; }

如果无法修改事件接口,如何重构以下方法?PMD报告太复杂,findbugs报告ITC_继承_类型_检查。还有魔法数字,如3、4、5等等

 public int getEventCode(Event event) {
        if (event instanceof OneEvent) {
            return 1;
    }
        if (event instanceof TwoEvent) {
            return 2;
        }
        if (event instanceof ThreeEvent) {
            return 3;
        }
        if (event instanceof FourEvent) {
            return 4;
        }
        if (event instanceof FiveEvent) {
            return 5;
        }
        if (event instanceof SixEvent) {
            return 6;
        }
        if (event instanceof SevenEvent) {
            return 7;
        }
        if (event instanceof EightEvent) {
            return 8;
        }
        if (event instanceof NineEvent) {
            return 9;
        }
        if (event instanceof TenEvent) {
            return 10;
        }
        return event.getClass().hashCode() + 10;
    }

您可以使用
列表是否有一些类型块在代码库周围浮动?如果是这样,用多态性替换条件可能会有所帮助。

好吧,使用instanceof不太好,但是如果您甚至不能更改事件接口以添加“int getType()”或类似内容,至少您可以重新构造代码:

使用“else-if”结构而不是just-if结构。我建议先把更深层次继承的事件类型放进去,然后考虑最后一个更一般的事件声明(如果你测试事件的事件实例,那么你将永远是正确的)。p> 这样至少可以降低复杂性

假设您的所有事件都直接实现了事件接口,并且没有其他需要检查的继承问题:

public int getEventCode(Event event) {
    int result = event.getClass().hashCode() + 10;
    if (event instanceof OneEvent) {
        result = 1;
    }
    else if (event instanceof TwoEvent) {
        result = 2;
    }
    else if (event instanceof ThreeEvent) {
        result = 3;
    }
    else if (event instanceof FourEvent) {
        result = 4;
    }
    else if (event instanceof FiveEvent) {
        result = 5;
    }
    else if (event instanceof SixEvent) {
        result = 6;
    }
    else if (event instanceof SevenEvent) {
        result = 7;
    }
    else if (event instanceof EightEvent) {
        result = 8;
    }
    else if (event instanceof NineEvent) {
        result = 9;
    }
    else if (event instanceof TenEvent) {
        result = 10;
    }
    return result;
}
我还更改了您的方法,因此它只声明一个返回变量,这通常被认为是一种更好的编码实践,因为它也有助于降低复杂性,即使在这种特殊情况下它没有真正的技术优势

但正如我所说,如果TenEvent扩展了FiveEvent,您也可能会遇到问题。在这种情况下,我建议使用您收到的事件实例的类,如下所示:

public int getEventCode(Event event) {
    int result = event.getClass().hashCode() + 10;
    String eventClass = event.getClass().getSimpleName();
    if ("OneEvent".equals(eventClass) {
        result = 1;
    }
    else if ("TwoEvent".equals(eventClass)) {
        result = 2;
    }
    return result;
}
我很懒,我只写了样本中的前两个,所以你知道了

甚至更好:

public int getEventCode(Event event) {
    int result = event.getClass().hashCode() + 10;
    Class eventClass = event.getClass();
    if (OneEvent.class.equals(eventClass) {
        result = 1;
    }
    else if (TwoEvent.class.equals(eventClass)) {
        result = 2;
    }
    return result;
}

这并不好——但是如果您不能更改事件类,这可能是解决您的需求的最面向对象的方法。也就是说,在不改变所讨论的课程的情况下

谢谢你。您的回答非常好,非常有用。您好,fge,我收到了一条警告“类型安全:ClassUhm的通用数组,是的,这个警告很痛苦……在变量声明之前放置一个
@SuppressWarnings(“unchecked”)
;或者如果您不喜欢它,使用一个静态初始化块。但是再次,由于
.hashCode()的问题我已经提到了,你应该认真考虑重构…有一天你会有一个非常令人讨厌的惊喜!谢谢FGE,重构正在进行中。谢谢马丁,但是在你的SoReC类类对象中仍然有很多“I/OR”是单独的:你可以使用<代码>=< /代码>来比较它们,不需要<代码>。(是的,这是一个罕见的事件,可以与Java中的==进行比较!)@mailzyok,你是对的,但它的圈复杂度比唯一if版本要低,因为所有if都是互斥的,因此改进了任何代码质量指标……在第一个版本中,它们可能是互斥的,因为你知道它们是互斥的,但对于代码质量工具,你可以潜在地将任何点击组合到ese ifs,增加圈复杂度。
public int getEventCode(Event event) {
    int result = event.getClass().hashCode() + 10;
    String eventClass = event.getClass().getSimpleName();
    if ("OneEvent".equals(eventClass) {
        result = 1;
    }
    else if ("TwoEvent".equals(eventClass)) {
        result = 2;
    }
    return result;
}
public int getEventCode(Event event) {
    int result = event.getClass().hashCode() + 10;
    Class eventClass = event.getClass();
    if (OneEvent.class.equals(eventClass) {
        result = 1;
    }
    else if (TwoEvent.class.equals(eventClass)) {
        result = 2;
    }
    return result;
}
public int getEventCode(OneEvent event) {
    return 1;
}
public int getEventCode(TwoEvent event) {
    return 2;
}
// etc.