2010-11-24 61 views
8

我有一個標誌參數的方法。我認爲將布爾值傳遞給方法是一種不好的做法(使簽名複雜化,違反了「每種方法做一件事」的原則)。我認爲將該方法分解爲兩種不同的方法會更好。但如果我這樣做,這兩種方法會非常相似(代碼重複)。是否有任何技術用標誌參數拆分方法?

我想知道是否有一些通用的技術用於將標誌參數拆分爲兩個獨立的方法。

這裏是我的方法(JAVA)的代碼:

int calculateNumOfLiveOrDeadNeighbors(Cell c, int gen, boolean countLiveOnes) { 
    int x = c.getX(); 
    int y = c.getY(); 
    CellState state; 
    int aliveCounter = 0; 
    int deadCounter = 0; 
    for (int i = x - 1; i <= x + 1; i++) { 
     for (int j = y - 1; j <= y + 1; j++) { 
     if (i == x && j == y) 
      continue; 
     state = getCell(i, j).getCellState(gen); 
     if (state == CellState.LIVE || state == CellState.SICK){ 
      aliveCounter++; 
     } 
     if(state == CellState.DEAD || state == CellState.DEAD4GOOD){ 
      deadCounter++; 
     } 
     } 
    } 
    if(countLiveOnes){ 
     return aliveCounter; 
    } 
    return deadCounter; 
} 

回答

3

我想這取決於每一個案件。

在這個例子中,你有兩種選擇,在我看來。

說你希望將電話calculateNumOfLiveOrDeadNeighbors()

一分爲二:

calculateNumOfLiveNeighbors() 

calculateNumOfDeadNeighbors() 

您可以使用Template Method到循環移動到另一個方法。 您可以用它來計算兩種方法中的死/活細胞。

private int countCells(Cell c, int gen, Filter filter) 
{ 
    int x = c.getX(); 
    int y = c.getY(); 
    CellState state; 
    int counter = 0; 
    for (int i = x - 1; i <= x + 1; i++) 
    { 
     for (int j = y - 1; j <= y + 1; j++) 
     { 
      if (i == x && j == y) 
       continue; 
      state = getCell(i, j).getCellState(gen); 
      if (filter.countMeIn(state)) 
      { 
       counter++; 
      } 
     } 
    } 
    return counter; 
} 

private interface Filter 
{ 
     boolean countMeIn(State state); 
} 

public int calculateNumOfDeadNeighbors(Cell c, int gen) 
{ 
    return countCells(c, gen, new Filter() 
         { 
          public boolean countMeIn(CellState state) 
          { 
           return (state == CellState.DEAD || state == CellState.DEAD4GOOD); 
          } 
         }); 
    } 

public int calculateNumOfLiveNeighbors(Cell c, int gen) 
{ 
    return countCells(c, gen, new Filter() 
         { 
          public boolean countMeIn(CellState state) 
          { 
           return (state == CellState.LIVE || state == CellState.SICK); 
          } 
         }); 
    } 

這很麻煩,甚至不值得痛苦。或者,您可以使用monad來存儲統計計算結果,然後在monad上使用getDeadCounter()getLiveCounter(),正如許多人已經提出的那樣。

+0

好主意,但使用靜態內部類來實現過濾器。 – Ralph 2010-11-24 12:09:06

4
  • 你可以嘗試在一個單一的方法來提取通用的功能只有使用特定功能
  • 你可以創建一個私有方法與該國旗,並從兩種公共方法調用它。因此,你的公共API不會有'複雜'的方法簽名,你不會有重複的代碼
  • 做一個方法返回兩個值,並在每個調用方(公共方法)中選擇一個。

在上面的例子中,我認爲第二個和第三個選項更適用。

1

似乎最乾淨的方法是返回一個包含兩個值的結果對象,並讓調用代碼從結果對象中提取它關心的內容。

+0

+1優化。否則,該方法應該被調用兩次以獲得死亡和活着的鄰居。 – khachik 2010-11-24 11:51:36

5

如果你不喜歡你的簽名布爾,你可以添加兩種不同的方法,沒有它,重構來private主要的一個:

int calculateNumOfLiveNeighbors(Cell c, int gen) { 
    return calculateNumOfLiveOrDeadNeighbors(c, gen, true); 
} 
int calculateNumOfDeadNeighbors(Cell c, int gen) { 
    return calculateNumOfLiveOrDeadNeighbors(c, gen, false); 
} 

OR

你可以編寫一個結果類別int數組作爲用於存儲兩個結果的輸出參數;這會讓你擺脫惱人的布爾參數。

+1

我寧願使用公有委託方法的私有方法而不是其他建議。 – heikkim 2010-11-24 12:13:51

1

IMO,這個所謂的「每種方法做一件事」的原則需要有選擇地應用。你的例子是,最好不要應用它。相反,我只是簡化的方法實現了一下:

int countNeighbors(Cell c, int gen, boolean countLive) { 
    int x = c.getX(); 
    int y = c.getY(); 
    int counter = 0; 
    for (int i = x - 1; i <= x + 1; i++) { 
     for (int j = y - 1; j <= y + 1; j++) { 
     if (i == x && j == y) 
      continue; 
     CellState s = getCell(i, j).getCellState(gen); 
     if ((countLive && (s == CellState.LIVE || s == CellState.SICK)) || 
      (!countLive && (s == CellState.DEAD || s == CellState.DEAD4GOOD))) { 
      counter++; 
     } 
     } 
    } 
    return counter; 
} 
1

像Bozho說:但是,但是在角落找尋其他方式結合點2和3:

創建一個(可能的私有方法)返回兩者(活的和死)和(僅當您需要在大多數情況下,生死未卜獨立),然後添加了兩個方法,挑死或既出結果:

DeadLiveCounter calcLiveAndDead(..) {} 
int calcLive(..) { return calcLiveAndDead(..).getLive; } 
int calcDead(..) { return calcLiveAndDead(..).getDead; } 
1

在使用重構方面,你可以做的一些事情是;

  • 複製方法並創建兩個版本,一個是真硬編碼,另一個是真硬編碼。您的重構工具應該幫助您內聯這個常量並根據需要刪除代碼。
  • 爲了向後兼容,重新創建調用如上所述的正確/錯誤方法的方法。然後你可以內聯這種方法。
0

有一個私人的方法,它是一個完全複製和粘貼你目前擁有的。 然後創建兩個新方法,每個方法都帶有一個更具描述性的名稱,只需調用您的私有方法即可使用適當的布爾值

1

我會傾向於保留CellState枚舉的地圖進行計數,然後添加LIVE和SICK或根據需要,DEAD和DEAD4GOOD。

int calculateNumOfLiveOrDeadNeighbors(Cell c, int gen, boolean countLiveOnes) { 
    final int x = c.getX(); 
    final int y = c.getY(); 
    final HashMap<CellState, Integer> counts = new HashMap<CellState, Integer>(); 
    for (CellState state : CellState.values()) 
     counts.put(state, 0); 

    for (int i = x - 1; i < x + 2; i++) { 
     for (int j = y - 1; j < y + 2; j++) { 
      if (i == x && j == y) 
       continue; 
      CellState state = getCell(i, j).getCellState(gen); 
      counts.put(state, counts.get(state) + 1); 
     } 
    } 
    if (countLiveOnes) 
     return counts.get(CellState.LIVE) + counts.get(CellState.SICK); 
    else 
     return counts.get(CellState.DEAD) + counts.get(CellState.DEAD4GOOD); 
} 
相關問題