私が取っているアプローチで問題が発生しています。間違った道をたどり始めて、私のアプローチを再考する必要があるのではないかと考えています。これが私がしようとしていることです。
Enumを使用して、考えられるさまざまなアカウントステータスを表したいと思います(重複するアプローチを使用して設定する他の有限データセットがあります)。
これらのアカウントステータスは、必要に応じてユーザーの言語で提示する必要があります。
例:アカウントのステータスがAの場合、英語を話す人は「アクティブ」、スペイン語は「アクティブ」と表示します。
また、適切なロケール設定で、考えられるすべてのアカウントステータスのドロップダウンリストを表示したい場合もあります。
(A、I、P)の値を持つAccountStatusEnumクラスを使用します。
プライベート静的メンバー変数に、ローカライズされたアカウントステータスのEnumMapを、可能なロケールのEnumMap内に格納します。
例:
private static EnumMap<LocaleEnum, EnumMap<AccountStatusEnum, String>> localeAccountStatuses = new EnumMap<LocaleEnum, EnumMap<AccountStatusEnum, String>>(LocaleEnum.class);
これは、静的初期化ブロック内でロードされます。
次に、次のメソッドを使用して、ドロップダウンのすべての値を取得できます。
public static EnumMap<AccountStatusEnum, String> getAccountStatuses(LocaleEnum locale) {
return localeAccountStatuses.get(locale);
}
または、このメソッドを使用して、特定のEnumの単一の説明を取得することもできます。
public String getDescription(LocaleEnum locale){
return getAccountStatuses(locale).get(this);
}
使用例:AccountStatusEnum.A.getDescription(LocaleEnum.es_MX);
このアプローチに対するあなたの考えと、同じことを達成するための考えられるより良いアプローチに興味があります。
[〜#〜] edit [〜#〜] Enumsに入力する値を取得するロジックは、単一のヘルパークラス内に集中化されます。したがって、説明のソースが新しいソースからのものに変更された場合、コードの変更は最小限に抑えられます。
ありがとう
ローカリゼーションの問題に取り組むのと同じように、この問題に取り組みます: ResourceBundle 。私は_I18n
_というクラスを使用します。このクラスには、キーとオプションで引数のリストを受け取るgetMessage
という静的メソッドがあります。キーは、デフォルトのResourceBundle
を使用するように構成されたLocale
で検索されるか、または任意のものを使用します(ここでの詳細は重要ではありませんが、_I18n
_の呼び出し元がLocale
が何であるかを知る必要があります)。
_I18n
_クラスは次のとおりです。
_public final class I18n {
private I18n() {
}
private static ResourceBundle bundle;
public static String getMessage(String key) {
if(bundle == null) {
bundle = ResourceBundle.getBundle("path.to.i18n.messages");
}
return bundle.getString(key);
}
public static String getMessage(String key, Object ... arguments) {
return MessageFormat.format(getMessage(key), arguments);
}
}
_
プロジェクトでは、パッケージpath.to.i18n、messages.properties(デフォルト)、messages_en.properties(ロケールen)、messages_it.properties(ロケールit)などを含むファイルにあります。
Enum値を変換する必要がある場合、キーがenum用語であることを除いて、他のキーと異なる扱いをする必要はありません。
言い換えれば、あなたは持っています:
_public enum AccountStatusEnum {
Active,
Inactive,
Pending
}
_
_I18n.getMessage
_を呼び出すときは、AccountStatusEnum.Active.toString()
を渡して、キーが「アクティブ」のプロパティファイルで変換を見つけます。私のようで、小文字のキーを使用したい場合は、文字列に対してtoLowerCase()
を実行する必要があります。さらによいのは、キーではなくEnumを受け取る新しい_I18n.getMessage
_を作成し、そのメソッドが列挙型の値を文字列に変換して小文字に変換した_I18n.getMessage
_の文字列バージョンを呼び出すことです。
したがって、これを_I18n
_クラスに追加します。
_ public static String getMessage(Enum<?> enumVal) {
return getMessage(enumVal.toString().toLowerCase());
}
_
デザインに影響を与えることなく、プログラムの同じ部分に同じ変換ロジックが組み込まれているため、私はこの方法を使用することを好みます。 enumキーを他のキーと区別することもできます。その場合は、各enumキーを「enum。」で始めることができるため、「enum」を付加します。 getMessage
を呼び出すとき。プロパティファイルでキーに名前を付けることを忘れないでください。
お役に立てば幸いです。
ResourceBundleを使用する方法ですが、列挙型がオブジェクトであることを利用して、内部にi19nの詳細を非表示にします
public enum MyEnum {
A,
I,
P;
private String localeText = null;
private MyEnum() {
// Load resource bundle
this.localeText = // get message;
}
public String getLocaleText() {
return this.localeText();
}
}
それはあなたがすることを可能にするでしょう:
MyEnum.A.getLocaleText();
直接、どこでも
最適化とは、静的イニシャライザでリソースバンドルを静的属性としてロードすることです。
JEEでは、リソースバンドルを注入可能にするためのボーナスポイント(ローカリゼーション文字列を簡単に変更できる場合があります)。
提案された回答の長所と短所を要約すると:
グローバルヘルパーファイルの問題は、柔軟性の欠如です。たとえば、アプリケーションに、特定の列挙型定数を持つさまざまな列挙型があり、一般的な形式に従っていない、非常に特定のキーが必要です。
列挙型でロジックを見つける際の問題はコードの複製であり、長期的には維持が難しくなります。
Java 8を使用すると、上記の問題の解決に非常に役立つ、デフォルトのメソッドという非常に役立つ機能を自由に利用できます。
私の提案は、キーを取得するための単一のメソッドを持つインターフェースを持つことです:
public interface I18nEnum {
default String getMessageKey(Enum<?> e) {
return e.getClass().getSimpleName() + '.' + e.name().toLowerCase();
}
}
このように、列挙型は、実際に実装せずに、そのインターフェースを実装することを宣言するだけで済みます。コードを1か所に配置できるという利点がありますが、必要に応じてデフォルトのメソッドをオーバーライドすることで特定のケースを処理できる柔軟性があります。例えば:
public enum Sex implements I18nEnum {
MALE,
FEMALE,
UNKNOWN {
@Override
public String getMessageKey(Enum<?> e) {
return "Common.UNKNOWN";
}
}
}