2012-01-04 173 views
21

這不是一個被卡住的問題,而是我正在尋找一種整潔的方式來編寫我的代碼。在枚舉中枚舉

本質上,我正在編寫一個事件驅動的應用程序。用戶觸發事件,事件被髮送到適當的對象,並且對象處理事件。現在我正在編寫偶處理程序方法,並且希望能夠使用switch語句來確定如何處理事件。現在,雖然我工作的總體結構,事件類是非常簡單的:

public class Event { 

    public static enum Action { 
     MOVE, FOO, BAR 
    } 

    private Action action; 
    private int duration; 

    public Event(Action action, int duration) { 
     this.action = action; 
     this.duration = duration; 
    } 

    public Action getAction() { 
     return action; 
    } 

    public int getDuration() { 
     return duration; 
    } 

然後,在另一個類,我會碰到這樣的:

public void handleEvent(Event evt) {  
    switch(Event.getAction()) { 
     case MOVE: doSomething(); break; 
     case FOO: doSomething(); break; 
     case BAR: doSomething(); break; 
     default: break; 
    } 
} 

我會做的就是這樣的事情(儘管我當然會堅持開關語句轉換成自己的職能,以避免它變成開關和案例討厭的毛球):

public void handleEvent(Event evt) {  
    switch(Event.getAction()) { 
     case MOVE: switch(Event.getAction()) { 
         case UP: break; 
         case DOWN: break; 
         case LEFT: break; 
         case RIGHT: break; 
        } 
     case FOO: break; 
     case BAR: break; 
     default: break; 
    } 
} 

所以,我想創建嵌套枚舉......像這樣:

public static enum Action { 
    public enum MOVE {UP, DOWN, LEFT, RIGHT}, FOO, BAR 
} 

它不象我無法迴避的情況下,這純粹是...方便。因此,儘管上述方法實際上並不奏效,但是有沒有類似的方法來實現這一點?如果我可以用動作「MOVE.UP」發送一個事件,並且該方法首先將其識別爲MOVE類型的動作,然後進一步確定它具體處於UP方向,那將會很好。這只是一個簡單的例子,如果我也可以製作更長的連鎖店,比如「DELETE.PAGE1.PARAGRAPH2.SENTENCE2.WORD11.LETTER3」,那就更好了。我看到它的方式,我將不得不使用字符串和大量的if/else語句。希望有更好的辦法! (哦,和性能事關我的情況下,如果有幫助)

+1

我不會用枚舉來描述你的事件。枚舉最適合可數且不變的狀態。上,下,左,右是好的,因爲他們不太可能改變。 MOVE,FOO,BAR覺得應該很容易添加。相反,我會使用多態。 (每個事件實現一個doSomething以獲得遊戲狀態)。 – ILMTitan 2012-01-04 20:14:02

回答

7

也許使用事件的繼承層次?

所以,你必須:

- abstract Event 
-- MoveEvent(Direction) 
-- FooEvent() 
-- BarEvent() 

它可能更有意義有:

- abstract Event 
-- abstract MoveEvent 
--- MoveUpEvent 
--- MoveDownEvent 
--- MoveRightEvent 
--- MoveLeftEvent 
-- FooEvent 
-- BarEvent 

如果所有的移動事件有一段距離,然後傳遞到MoveEvent構造函數(這將波及下)。

22

我相信在Java中,只要你的非枚舉常量是第一位的,你可以簡單地嵌套枚舉。

enum Action 
{ 
    FOO, 
    BAR; 
    enum MOVE 
    { 
     UP, 
     DOWN, 
     LEFT, 
     RIGHT 
    } 
} 

這個編譯給我,並給我你正在尋找的行爲。

+6

有趣。 MOVE不是行動。 Action.values()只有FOO和BAR – 2012-01-05 02:00:49

+0

雖然,Action.MOVE。UP是完全有效的 – 2012-01-05 15:02:41

+2

是的,但你需要知道這一點。沒有辦法輕鬆遍歷所有的枚舉實例。 – 2012-01-05 23:30:31

2

你可以像這樣以任意順序嵌套它們:

包嵌套;

import java.util.*; 
import nested.Citrus.Orange; 
interface HasChildren { 
    Set<Enum<?>> children(); 
} 
enum Citrus implements HasChildren { 
    lemon, lime, orange; 
    Set<Enum<?>> children; 
    enum Orange implements HasChildren { 
     navel, valencia, blood; 
     Set<Enum<?>> children; 
     enum Navel implements HasChildren { 
      washinton, lateLane, caraCaraPink; 
      public Set<Enum<?>> children() { 
       return null; 
      } 
     } 
     static { 
      navel.children = new LinkedHashSet<Enum<?>>(); 
      navel.children.addAll(EnumSet.allOf(Navel.class)); 
     } 
     enum Blood implements HasChildren { 
      moro, taroco; 
      public Set<Enum<?>> children() { 
       return null; 
      } 
     } 
     static { 
      blood.children = new LinkedHashSet<Enum<?>>(); 
      blood.children.addAll(EnumSet.allOf(Blood.class)); 
     } 
     public Set<Enum<?>> children() { 
      return children != null ? Collections.unmodifiableSet(children) : null; 
     } 
    } 
    static { 
     orange.children = new LinkedHashSet<Enum<?>>(); 
     orange.children.addAll(EnumSet.allOf(Orange.class)); 
    } 
    public Set<Enum<?>> children() { 
     return children != null ? Collections.unmodifiableSet(children) : null; 
    } 
} 
public class EnumTreeNested { 
    static void visit(Class<?> clazz) { 
     Object[] enumConstants = clazz.getEnumConstants(); 
     if (enumConstants[0] instanceof HasChildren) for (Object o : enumConstants) 
      visit((HasChildren) o, clazz.getName()); 
    } 
    static void visit(HasChildren hasChildren, String prefix) { 
     if (hasChildren instanceof Enum) { 
      System.out.println(prefix + ' ' + hasChildren); 
      if (hasChildren.children() != null) for (Object o : hasChildren.children()) 
       visit((HasChildren) o, prefix + ' ' + hasChildren); 
     } else 
      System.out.println("other " + hasChildren.getClass()); 
    } 
    static <E extends Enum<E> & HasChildren> Set<E> foo() { 
     return null; 
    } 
    public static void main(String[] args) { 
     System.out.println(Citrus.Orange.Navel.washinton); 
     visit(Citrus.lemon, ""); 
     System.out.println("----------------------"); 
     visit(Citrus.orange, ""); 
     System.out.println("----------------------"); 
     visit(Citrus.class); 
     System.out.println("----------------------"); 
    } 
}