2012-05-09 41 views
2

我想上重構下面的方法了一些建議:重構嵌套開關對象

public boolean makeDecision(String group, int level, int primaryAmount, int secondaryAmount) 
{ 
    if (group.equals("A")) 
    { 
     switch (level) 
     { 
      case 0 : return primaryAmount > 10000;break; 
      case 1 : return primaryAmount > 20000;break; 
      default : return secondaryAmount > 30000; break; 
     } 
    } 
    else if (group.equals("B")) 
    { 
     switch (level) 
     { 
       case 0 : return primaryAmount > 40000;break; 
       case 1 : return primaryAmount > 50000;break; 
       default : return secondaryAmount > 60000; break; 
     } 

    } 
    else if (group.equals("C")) 
    { 
     switch(level) 
     { 
      case 0 : return primaryAmount > 70000;break; 
      case 1 : return primaryAmount > 80000;break; 
      default : return secondaryAmount > 90000; break; 
     } 

    } 
    return false; 
} 

想我實現:

  • 允許代碼遵循開啓/關閉原則,因爲會有更多的團體/級別及時。
  • 刪除'level'開關語句中的重複項。
  • 理想情況下,刪除「組」頂級開關語句。

回答

1

組看起來像他們有行爲。您可以將字符串組提升爲第一類類型。你也可以在類上放置方法來表示你得到的邏輯。我在變量上加上了愚蠢的名字,他們可以用更好的名字做。

public class Group { 
    public static Group A = new Group(10000,20000,30000); 
    public static Group B = new Group(40000,50000,60000); 
    public static Group C = new Group(70000,80000,90000); 

    private int primaryMin; 
    private int primaryMid; 
    private int secondaryMax; 

    private Group(int min, int mid, int max) { 
     primaryMin = min; 
     primaryMid = mid; 
     secondaryMax = max; 
    } 

    public boolean getLevel(int level, int primaryAmount, int secondaryAmount) { 
     if (level == 0) 
     return primaryAmount > primaryMin; 
     else if (level == 1) 
     return primaryAmount > primaryMid; 
     else 
     return secondaryAmount > secondaryMax; 
    } 
} 

所以現在你可以減少你的頂級語句到

public boolean makeDecision(Group group, int level, int primaryAmount, int secondaryAmount) { 
    return group.getLevel(level, primaryAmount, secondaryAmount); 
} 

您不妨考慮使用null object pattern處理未知組。

如果你說層次會及時增長,那麼我會考慮再次做幾乎完全相同的類來引入Level類,並將if/else鏈作爲另一層polymorpshim。這將成爲double dispatch pattern首先你會發送的類型Group,然後在Level的類型。這應該意味着您可以添加新代碼而無需修改現有代碼。

+0

我將如何派遣組的類型?你是說我應該爲每個小組分別開一堂課嗎? – Michael

+0

通過派遣,我只是指在組上調用方法。所以上面例子中的'group.GetLevel'。目前,組不是類層次結構,因爲邏輯足夠簡單以適合一個地方。你可以爲每個組寫一個不同的子類,但是由於它們只是在數據而不是行爲上有所不同,所以我不會那樣做。同樣適用於Level。如果真的在行爲上有所不同,我只會添加新的子類。 –

1

由於每種情況都是通過一個平凡的比較來計算的,所以您可以同時進行所有比較。

所以這裏有一個建議:

boolean[] aSol = { primary > 10000, primary > 20000, secondary > 30000 }; 
boolean[] bSol = { primary > 40000, primary > 50000, secondary > 60000 }; 
boolean[] cSol = { primary > 70000, primary > 80000, secondary > 90000 }; 

level = Math.min(level, 2); 
return group.equals("A") ? aSol[level] : 
     group.equals("B") ? bSol[level] : 
     group.equals("C") ? cSol[level] : 
     false; 

我認爲這是相當的可讀性和可維護性。

這裏的另一種略有不同的配方:

boolean[][] result = { 
     { primary > 10000, primary > 20000, secondary > 30000 }, 
     { primary > 40000, primary > 50000, secondary > 60000 }, 
     { primary > 70000, primary > 80000, secondary > 90000 } }; 

int groupId = Arrays.asList("A", "B", "C").indexOf(group); 

if (groupId == -1) 
    return false; 

boolean[] groupResult = result[groupId]; 
return groupResult[Math.min(level, groupResult.length-1)]; 

另一種選擇是創建一個接口與方法

makeDecision(int level, int primaryAmount, int secondaryAmount) 

然後填充具有決策程序Map<String, GroupDecision>

groupMap.put("A", new GroupDecision() { ... }); 
groupMap.put("B", new GroupDecision() { ... }); 
groupMap.put("C", new GroupDecision() { ... }); 

然後致電

return groupMap.get(group).makeDecision(level, primaryAmount, secondaryAmount); 

這種方法可能是最具擴展性和可讀性的方法。

+0

但如果我有一個新的水平,然後aSol,bSol和cSol都將需要修改? – Michael

+0

你能否澄清你的擔憂?該程序需要完整的權利?什麼解決方案可以讓你增加可能級別的數量,而不需要修改代碼? – aioobe

+0

我擔心的是,如果出現新的級別,我不想修改*存在的*代碼。我想添加* new *代碼來處理它,這樣我就可以遵循開閉原則。 – Michael