5

以下の getCategory メソッドは非常に冗長なようです。おそらく Enum を使用してクリーンにするためにリファクタリングすることについて誰か提案があるかどうか疑問に思っていました。渡された「val」に基づいて、Category クラスから適切な Category インスタンスを返すには getCategory が必要です。Category クラスは生成された JNI コードなので、変更したくありません。誰にもアイデアはありますか?

リファクタリングするメソッド:

private Category getCategory(String val) throws Exception{
        Category category;
        if (val.equalsIgnoreCase("producer")) {
            usageCategory = Category.CATEGORY_PRODUCER;
        } else if (val.equalsIgnoreCase("meter")) {
            usageCategory = Category.CATEGORY_METER;
        } else if (val.equalsIgnoreCase("consumer")) {
            usageCategory = Category.CATEGORY_CONSUMER;
        } else {
            throw new Exception("Invalid value: " + val);
        }       
        return usageCategory;
    }

Category.java: 生成された JNI (これは変更できません):

public final class Category {
  public final static Category CATEGORY_PRODUCER = new Category("CATEGORY_PRODUCER", SampleJNI.CATEGORY_PRODUCER_get());
  public final static Category CATEGORY_METER = new Category("CATEGORY_METER", SampleJNI.CATEGORY_METER_get());
  public final static Category CATEGORY_CONSUMER = new Category("CATEGORY_CONSUMER", SampleJNI.CATEGORY_CONSUMER_get());

}
4

3 に答える 3

6

あなたの方法は本質的に所定からにマッピングされているので、代わりに使用してみませんか?特に、これらのマッピングは静的であるため、Guavaをお勧めします。StringCategoryMapImmutableMap

private static final ImmutableMap<String, Category> CATEGORIES_BY_STRING =
        ImmutableMap.of(
            "producer", Category.CATEGORY_PRODUCER,
            "meter", Category. CATEGORY_METER,
            "consumer", Category.CATEGORY_CONSUMER
        );

または、サードパーティのライブラリを使用したくない場合の標準的な方法:

private static final Map<String, Category> CATEGORIES_BY_STRING;
static {
    Map<String, Category> backingMap = new HashMap<String, Category>();
    backingMap.put("producer", Category.CATEGORY_PRODUCER);
    backingMap.put("meter", Category.CATEGORY_METER);
    backingMap.put("producer", Category.CATEGORY_CONSUMER);
    CATEGORIES_BY_STRING = Collections.unmodifiableMap(backingMap);
}

この方法を使用して、無効な値をチェックすることもできます(David Harknessが指摘したように、大文字と小文字を区別しないことをサポートします)。

private Category getCategory(String val) {
    Category category = CATEGORIES_BY_STRING.get(val.toLowerCase());
    if (category == null) {
        throw new IllegalArgumentException();
    }
    return category;
}

列挙型の使用について:

Stringに渡されるsを完全に制御でき、リテラル値のみを渡す場合は、代わりgetCategoryに切り替えるのが理にかなっています。enum

編集:以前は、EnumMapこの場合にを使用することをお勧めしましたが、エイドリアンの答えははるかに理にかなっています。

于 2012-04-05T04:13:38.707 に答える
5

列挙型に基づいてリファクタリングしたいとおっしゃった場合は、文字列を渡してgetCategoryにこれらすべての作業を実行する必要がなくなったことを意味します。コードは、Stringを使用する代わりに、enumを直接使用しています。

この場合は、読み続けてください

幸いなことに、カテゴリは静的変数であるため、本当に簡単なことを行うことができます

public enum FooCategory {  // give a better name yourself
  PRODUCER(Category.CATEGORY_PRODUCER),
  METER(Category.CATEGORY_METER),
  CONSUMER(Category.CATEGORY_CONSUMER)

  private Category category;
  FooCategory(Category category) {
    this.category=category;
  }
  Category getCategory() {
    return this.category;
  }
}

古いコードでは、次のようなことをしています。

String fooCategory = "producer";
//....
Category category = getCategory(fooCategory);
// work on category

今、あなたはもっときちんとしたことをしています

FooCategory fooCategory = FooCategory.PRODUCER;
//...
Category category = fooCategory.getCategory();
// work on category
于 2012-04-05T04:39:07.093 に答える
1

Category@PaulBellora と @AdrianShum の回答はどちらも素晴らしいですが、ストレージ上の理由から、「プロデューサー」(大文字と小文字を区別しない) のような魔法の値を使用することは避けられないと思います。したがって、冗長なコードgetCategoryも避けられないのではないかと思います。(残念ながら、initCategoryと getに使用されるマジック値Categoryは同じではありません)

使用するコードは次のEnumとおりです (Java 1.5 以降)。

public enum Category {
    CATEGORY_PRODUCER,
    CATEGORY_METER,
    CATEGORY_CONSUMER;

    public static Category of(String val) throws Exception {
        Category usageCategory;
        if (val.equalsIgnoreCase("producer")) {
            usageCategory = Category.CATEGORY_PRODUCER;
        } else if (val.equalsIgnoreCase("meter")) {
            usageCategory = Category.CATEGORY_METER;
        } else if (val.equalsIgnoreCase("consumer")) {
            usageCategory = Category.CATEGORY_CONSUMER;
        } else {
            throw new Exception("Invalid value: " + val);
        }       
        return usageCategory;
    }
}

生成、取得、保存に同じマジック値を使用すると、次のことが可能になります。

public enum Category {
    CATEGORY_PRODUCER("producer"),
    CATEGORY_METER("meter"),
    CATEGORY_CONSUMER("consumer");

    private String category;
    private Category(String category) {
        this.category = category;
    }

    public static Category of(String val) throws Exception {
        Category usageCategory;
        // You can use equals not equalsIgnoreCase, so you can use map to avoid redundant code.
        // Because you use the same magic value everywhere.
        if (val.equals("producer")) {
            usageCategory = Category.CATEGORY_PRODUCER;
        } else if (val.equals("meter")) {
            usageCategory = Category.CATEGORY_METER;
        } else if (val.equals("consumer")) {
            usageCategory = Category.CATEGORY_CONSUMER;
        } else {
            throw new Exception("Invalid value: " + val);
        }       
        return usageCategory;
    }
}

次のように作成しますCategory

Category category = Category.of("producer");

もちろん、コードを変更して を含める必要がありますSampleJNI.CATEGORY_CONSUMER_get()

于 2012-04-05T05:31:38.847 に答える