2

データが複数の場所からクエリされ、最初の非 null インスタンスで返される必要がある場合に、if/else ステートメントの使用を避ける方法はありますか?

3 つの異なる場所 (ユーザー設定、グループ設定、システム設定) からユーザーの設定を読み込もうとしています。例えば:

Preference getPreference(User user, Preference.Type type) {

    Preference preference = getUserPreferenceFor(user, type);
    if (preference != null) {
        return preference;
    }

    preference = getGroupPreferenceFor(user, type);
    if (preference != null) {
        return preference;
    }

    return getSystemPreferenceFor(user, type);
}     

これらの if チェックの使用を避け、これらのメソッドを連鎖させて、動作は同じままですが、コードにこの醜い重複がないようにしたいと思います。

私はいくつかの解決策を考えましたが、これらのストライキはエレガントなものではありません。たとえば、1 つの方法は、これらのメソッドのそれぞれにデフォルト自体を提供させることですが、それは if ステートメントを分散させるだけです。

Preference getPreference(User user, Preference.Type type) {
    Preference preference = getUserPreferenceFor(user, type);
    if (preference != null) {
        return preference;
    }

    return getGroupPreferenceFor(user, type);
}

Preference preference getGroupPreferenceFor( 
    if (preference != null) {
        return preference;
    }

    return getSystemPreferenceFor(user, type);
} 

もう 1 つの方法は、いくつかのプロバイダー インターフェイスを使用し、それぞれにサブクラスを作成し、最初の非 null が見つかるまでプロバイダーを反復処理することです。

public interface PreferenceProvider {
    Preference getPreference(User user, Preference.Type type);
}

public class UserPreferenceProvider implements PreferenceProvider {
    public Preference getPreference(User user, Preference.Type type) {
        ...
    }
}
... group and system provider the same way

final static PreferenceProvider[] providers = new PreferenceProvider[] {
    new UserPreferenceProvider(),
    new GroupPreferenceProvider(),
    new SystemPreferenceProvider()
};

Preference getPreference(User user, Preference.Type type) {
    Preference preference = null;
    for (PreferenceProvider provider : providers) {
        preference = provider.getUserPreferenceFor(user, type);
        if (preference != null) {
            return preference;
        }
    }
}

最後のものは十分に近いですが、まだこのヌル チェックがあり (これは避けたいと思います)、この問題を解決する設計パターンがあると確信しています。どっちかしか思い出せない…

4

5 に答える 5

2

どうですか:

Preference getPreference(User user, Preference.Type type) {

    Preference preference = getUserPreferenceFor(user, type);
    if (preference == null) {
        preference = getGroupPreferenceFor(user, type);
        if (preference == null) {
           preference = getSystemPreferenceFor(user, type);
        }
    }
    return preference;
}

まだifs を使用していますが、私には十分にエレガントに見えます。

于 2013-08-12T18:52:39.677 に答える
0

これを行うには、ラッパー (デコレータ)パターンを使用することをお勧めします。

各チェックを 1 つのオブジェクトにラップし、すぐに装飾されたオブジェクトを作成するだけです。ウィキペディアには、それを使用する良い例があります。

幸運を。

于 2013-08-12T19:40:17.847 に答える
0

さまざまな実装で2番目のアイデアを使用しますが、値を提供できるかどうかを確認するために使用できるProvider2番目のメソッドをそれぞれに追加します。Provider次のように、null の戻り値をチェックする代わりに、そのメソッドを使用できます。

for (PreferenceProvider provider : providers) {
    if (provider.canProvideAPreferenceFor(user, type)) {
        return provider.getUserPreferenceFor(user, type);
    }
}

return null;
于 2013-08-12T18:55:19.297 に答える
0

指定された設定のセットを使用して、Preferences クラスを変更可能にすることができます。

Preference getPreference(User user, Preference.Type type) {

    Preference preference = new Preference( getSystemPreferenceFor(user, type) );

    preference.merge( getGroupPreferenceFor(user, type) );
    preference.merge( getUserPreferenceFor(user, type) );

    return preference;

}

マージは null をチェックする必要がありますが、単一のインスタンスでのみです。Preference.Preference() は、適切な場合、デフォルトで getSystemPreference にすることができます。

これは、設定の 1 つのセットのみが使用されるという前提を変更します。

于 2013-08-12T18:56:12.367 に答える