2012-01-04 46 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; 
    } 
} 

を私は何を希望以下のように行うにはは(私はもちろん、スイッチと例の厄介な毛玉に回し、それを避けるために、独自の関数にswitch文を貼り付けますが)このようなものです:

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

あなたのイベントを記述するためにenumを使用しません。列挙型は、数え切れないほどの状態のセットに最適です。 UP、DOWN、LEFT、RIGHTは変化しにくいので良いです。 MOVE、FOO、BARは簡単に追加できるように感じます。代わりに私は多型を使用します。 (各イベントは、ゲーム状態をとるdoSomethingを実装しています)。興味深いことに – ILMTitan

答えて

7

多分、イベントの継承階層を使用しますか?

だから、あなたが持っている:そして、リップルれる(MoveEventのコンストラクタにそれを渡し、

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

をすべて移動イベントは距離がある場合:

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

をそれは持っているより多くの意味を行うことができますダウン)。

22

私は、Javaでは、非enum定数が最初に来る限り、単に列挙型を入れ子にすることができます。

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

これは私のためにコンパイルし、あなたが探していた動作を教えてくれます。

+6

。 MOVEはアクションではありません。 Action.values()はFOOとBARを持っているだけです –

+0

、Action.MOVE。UPは完全に有効です –

+2

はい、それを知る必要があります。すべての列挙型インスタンスを簡単に反復処理する方法はありません。 –

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("----------------------"); 
    } 
}