1

在其自己的類中聲明的枚舉結構是業務邏輯類的成員變量。那個枚舉基本上代表了另一個類的狀態。在枚舉結構上盤旋時重構和刪除case語句

雖然我重新審視這個問題好幾次,替換或刪除那些case語句被證明相當令人沮喪的我。

幾個業務邏輯方法簡單遍歷枚舉和通過分配相同的枚舉的另一個值改變類的狀態下,和其它性質。

public enum MyEnum{ A,B,C,D } 

業務邏輯類有該枚舉作爲成員:

public class BusinessLogic { 

    private MyEnum CurrentSelection; 
    private int propertyX; 
    private int propertyY; 

    public void operation1(){ 
     switch(CurrentSelection){ 
     case A: {alter propertyX this way; break;} 
     case B: {alter propertyY this way; break;} 
     case C: {alter propertyX that way; break;} 
     case D: {alter propertyY that way; break;} 
     } 

    } 

    public void operation2(){ 
     switch(CurrentSelection){ 
     case A: {CurrentSelection=MyEnum.B; break;} 
     case B: {CurrentSelection=MyEnum.C; break;} 
     ....etc 
     } 
    } 

    public void operation3(){ 
     switch(CurrentSelection){ 
     case A: {CurrentSelection=MyEnum.D; break;} 
     case B: {CurrentSelection=MyEnum.A; break;} 
     ....etc 
     } 
    } 
} 

另一個客戶端類將實例業務邏輯的類,草簽它的屬性,然後使用它的操作方法。

我已經成功做了什麼(從SO幫助)是封裝的操作方法到命令模式結構,這樣我就可以調用的操作沒有任何case語句。 (here)。

我想我的麻煩是如何在我的業務邏輯類中封裝case語句。我懷疑我需要多態性和適當的數據結構。

重構專家建議每個case語句應該是一個通用接口的實現。但是,如果我有3個方法遍歷4個成員的枚舉,這意味着我可能需要3個接口和4個實現,給我12個類(加上3個接口)。這不是一個超負荷的類嗎?這3種方法的邏輯工作正常,但問題在於重複開關/情況聲明。

有沒有一種方法來重構這些switch語句,但避免多態性名其他類無數?是否可以將迭代遍歷枚舉部分分解出來?或者只是案例(其中的邏輯是)應該被重構?


作爲第一步予除去那些方法完全我具有它們執行一個簡單的接口:

public interface Command { 
    void execute(); 
} 

所以,其操作方法實現的命令接口:

public class Operation1 implements Command { 

    private void doOperation1(){ 
     switch(CurrentSelection){ 
      ..all the cases here 
     }  
    } 

    public void execute() { 
     doOperation1(); 
    } 

} 

正如我看到這一點,它會買我一個更清潔的商業邏輯課程,但切換案例的痕跡將保持不變,對吧?

回答

1

你可能包括一個接口的所有三種方法,並有一個接口(每個枚舉)的不同的實現,並有該樓內設有商務類代表的電話..

也改變了狀態,有回報來自操作的值是該通用接口,以便在調用這些方法時,調用類可以爲下一個狀態返回適當的對象。

+0

謝謝你的回覆。 是的,但是這些單獨的實現是否仍然帶有switch/case語句?我將清理業務邏輯和客戶端類,但實現3個接口中的每一個的新類仍然會在其中包含交換機案例。 我的推理是否正確,或者您可能不介意詳細闡述 – denchr 2009-09-08 20:37:26

+0

您可以通過枚舉本身訪問不同的類 - 即枚舉實現接口或類似的東西,然後執行操作,所以你根本不必打開它。這與命令模式類似。 – aperkins 2009-09-08 20:44:31

1

要闡述我的意見,並逐漸接近,我認爲RMN在談論,你可以做到以下幾點:

public interface MyInterface { 
    operation1(property); 
    operation2(property); 
    operation3(property); 
} 

public enum MyEnum implements MyInterface { 
    A { 
     operation1(property) { 
      //Do Stuff 
     } 
     operation2(property) { 
      //Do Stuff 
     } 
     operation3(property) { 
      //Do Stuff 
     } 
    }, 
    B { 
     operation1(property) { 
      //Do Stuff 
     } 
     operation2(property) { 
      //Do Stuff 
     } 
     operation3(property) { 
      //Do Stuff 
     } 
    }, 
    C { 
     operation1(property) { 
      //Do Stuff 
     } 
     operation2(property) { 
      //Do Stuff 
     } 
     operation3(property) { 
      //Do Stuff 
     } 
    }, 
    D { 
     operation1(property) { 
      //Do Stuff 
     } 
     operation2(property) { 
      //Do Stuff 
     } 
     operation3(property) { 
      //Do Stuff 
     } 
    } 
} 

這就讓你有一個命令模式 - 即的東西做的工作爲你選擇不同的元素。它也類似於狀態模式,儘管這裏的重點在於執行而不是數據或數據狀態。

希望這會有所幫助。

+2

這正是我所說的,只需要操作返回MyInterface,以便您可以在調用函數時更改狀態。類似於 MyInterface操作1(屬性){do stuff,dont change state return this; } 和: MyInterface操作2(屬性){ //做東西並且改變狀態 return A(); } 然後u可以使用它作爲: currstate = currstate.operation1() 就大功告成了 – rmn 2009-09-08 20:58:54

+0

謝謝,我會盡力爲併入到這個問題的邏輯。我承認我不能看到它的作用,因爲操作方法是業務邏輯對象行爲的一部分。我仍然需要將該對象委託給枚舉結構嗎? - 道歉,如果我的問題有點混亂。我需要試驗你的建議,得出一些結論,然後制定一個更準確的問題。 – denchr 2009-09-08 21:02:41

+0

@rmn我知道這是你所建議的,這就是爲什麼我向你投票的原因。我只是認爲他可能需要一個更好的例子,並且想給它,這些評論框並不真正允許。 – aperkins 2009-09-08 21:05:42

0

正如您可能從其他答案中猜到的那樣,這是一個常見問題,並已被編碼爲Martin Fowler的重構。看看重構Replace Conditional with Polymorphism。 Joshua Kerievsky也有類似的編碼重構(Replace Conditional with Strategy)。

+0

是的,這就是我所說的:在我原來的文章中,「重構專家建議每個案例陳述應該是一個通用界面的實現」。然而,在這一個中,這對我來說並不簡單。 – denchr 2009-09-08 21:08:28