2013-07-05 52 views
3

如果無法修改Event接口,如何重構以下方法? PMD報告太複雜,findbugs報告ITC_INHERITANCE_TYPE_CHECKING。還有幻數,如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; 
    } 

回答

3

可以使用例如一個List<Class<?>>

private static final List<Class<? extends Event>> EVENT_CLASSES 
    = Arrays.asList(OneEvent.class, ...); 

然後:

public int getEventCode(final Event event) 
{ 
    final Class<? extends Event> c = event.getClass(); 
    final int index = EVENT_CLASSES.indexOf(c); 
    return index != -1 ? index + 1 : c.hashCode() + 10; 
} 

注:需要事件的確切類的,不是得到的(即OneEvent而不是OneDerivedEvent)。否則,測試稍微複雜一點,但仍然可行。

至於:

FindBugs的報告ITC_INHERITANCE_TYPE_CHECKING

是的,這是因爲instanceof檢查。

但是:代碼有一個基本缺陷。 不能保證.hashCode()在兩個不同的JVM執行之間返回相同的值。更重要的是,它可以返回負值。這意味着它可以返回,例如-4作爲一個值;這意味着6將返回「其他事件」,因此與SixEvent衝突。

考慮一個重構!

+0

謝謝fge。你的回答非常好,非常有幫助。 – mailzyok

+0

嗨fge,我得到了一個警告:「類型安全:爲<可變參數>創建一個Class <?extends Event的通用數組>」 private static final List > EVENT_CLASSES = Arrays.asList(OneEvent.class,...); 這是一場虛驚,對吧?任何最佳做法,以消除此警告? – mailzyok

+1

呃,是的,這個警告是一種痛苦......在變量聲明之前放置@SuppressWarnings(「unchecked」)';或者如果你不喜歡它,請使用靜態初始化塊。 – fge

0

這些類型的塊是否有一些在代碼庫中浮動?如果是這樣的話,可能會有所幫助。

0

嗯,這是不好的instanceof使用,但如果你不能改變事件接口甚至添加「詮釋的getType()」或類似的,至少你可以調整你的代碼:

使用「否則如果「結構,而不是結構。我建議首先放置更深的繼承的事件類型,然後再考慮更一般的事件聲明(如果測試事件instanceof事件,您將始終成爲true)。

這種方式至少可以降低複雜性。

假設所有的活動直接實現事件接口,而且沒有其他繼承問題進行檢查:

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; 
} 
+0

謝謝Martin,但你的解決方案中仍然有很多「if/else」 – mailzyok

+1

類對象是單例:你可以使用==來比較它們,不需要'.equals()'(是的,這是一個罕見的事件,你可以用Java比較==!)。 – fge

+0

@mailzyok,你是對的,但是它的圈複雜度比唯一的版本低,因爲所有的if都是互斥的,從而提高了任何代碼質量指標......在第一個版本中,它們可能是互斥的,因爲你知道它們是,但是對於代碼質量工具,您可能會將這些命中的任意組合添加到這些ifs中,從而增加圈複雜度。 – Martin

1
public int getEventCode(OneEvent event) { 
    return 1; 
} 
public int getEventCode(TwoEvent event) { 
    return 2; 
} 
// etc. 

這是不好的 - 但是如果你不能改變事件類,這可能是解決你的需求是最面向對象的方式。這是replacing conditional with polymorphism,沒有改變有問題的類

相關問題