2017-01-17 3 views
5
の両端に現れる方法をファクタリング

私はname財産およびそれらのすべてのために大体このようなものですbyName方法にはいくつかの列挙型があります。byName方法が異なる列挙型の間で複製されているので多くの列挙型

public static Condition byName(String name) throws NotFoundException { 
    for (Condition c : values()) { 
     if (c.name.equals(name)) { 
      return c; 
     } 
    } 

    throw new NotFoundException("Condition with name [" + name + "] not found"); 
} 

を、私はそれを一箇所に分解し、重複したコードを避けたいと思います。

しかし:

  • 列挙型は、デフォルトの方法で
  • Java8インタフェースはvalues()方法

にアクセスすることができない私は、これはおそらく、AspectJので行うことができる知っているが、私は」抽象クラスを拡張することはできませんdではなく、Spring AOP(これはSpringプロジェクトであるため手元にあります)では、既存のメソッドにバインドするだけで、新しいメソッドを追加することはできません。

一般的な方法を列挙型に追加する実行可能なソリューションはありますか?

+0

あなたが別のクラスに、これらの列挙型をラップすることはできません(1つの列挙型あたりクラス)...そして、このクラスは、この 'byName'メソッドで抽象クラスを拡張しますか? –

答えて

7

は、私が同じ状況にやったことだ

Condition c = EnumWithNames.byName(Condition.class, "Name 1"); 

cls.getEnumConstants()values()と同じです。

+2

'EがEnumであることも要求できます:' &EnumWithNames> '。これにより、 'values()'コールを使うことができます。 – Thirler

+0

@Thirler 'T'型を絞り込むことはできますが、暗黙のメソッド' values() 'を呼び出すことはできません。 – Flown

+3

'E extends Enum &EnumWithNames>' 'として' E 'を宣言すると、 'values()'メソッドを呼び出すことはできませんが、呼び出し元がこのメソッドが動作しない非 ' 。 – Holger

0

静的ユーティリティメソッドを作成し、その列挙型自体の内部でユーティリティメソッドを使用することができます。あなたはまだ少し重複している。それを行うもっと良い方法の確信。

public static T staticByName(String name, Class<T> clazz) { 
    for (T c : values()) { 
     if (c.name.equals(name)) { 
      return c; 
     } 
    } 

    throw new NotFoundException("Condition with name [" + name + "] not found"); 
} 

と列挙型で

public static Condition byName(String name){ 
    return Utility.staticByName(name, Condition.class); 
} 

代わりに、あなたはそれが少しより効率的にするために列挙型のインスタンスでマップにアイテムを置くことができます。

上記のコードはテストされていないので、おそらくEnumsで動作するように修正する必要がありますが、それはそのアイデアを全面的に受け取ります。

public interface EnumWithNames { 
    String getName(); 

    static <E extends EnumWithNames> E byName(Class<E> cls, String name) { 
     for (E value : cls.getEnumConstants()) { 
      if (Objects.equals(value.getName(), name)) return value; 
     } 
     throw new IllegalArgumentException("cannot identify " + cls.getName() + " value by name " + name); 
    } 
} 

public enum Condition implements EnumWithNames { 
    private String name; 
    ... 

    @Override 
    public String getName() { return name; } 
} 

そして、私は名前で列挙型の値を見つける必要があるとき、私は呼び出し::ここで

+0

私はあなたが良いアイデアを持っていると思う、あなたの列挙型のインスタンスが必要なので、私のソリューションはかなり役に立たない。ただ1つの問題があります。あなたは何もせずに 'values'を呼び出しています。 –

2

私は少し遅れて、ここでパーティによように思える..しかし、ここで私はこのような場合のための場所に持っているものです。

static interface Nameable { 

     static <T extends Enum<T>> T byName(Class<T> clazz, String name) { 

      return EnumSet.allOf(clazz) 
       .stream() 
       .filter(i -> i.name().equals(name)) 
       .findFirst() 
       .orElseThrow(IllegalArgumentException::new); 
    } 
}