3

URLを作成するために使用される入力としてジェネリック型をとるメソッドを指定するインターフェースがあります。

interface UrlGenerator<T> {

    String prepareUrl( T input );

}

パラメータを必要としない実装が1つあります。ジェネリック型TにはVoidを使用します。

class StaticUrlGenerator implements UrlGenerator<Void> {

    private final String url;

    public StaticUrlGenerator( String url ) {
        this.url = url;
    }

    @Override
    public String prepareUrl( Void nothing ) {
        return url;
    }

}

StaticUrlGeneratorは、prepareUrlメソッドの引数としてnullを必要とするため、使いにくいです。

パラメータを失う可能性がありinputます:

interface UrlGenerator<T> {

    String prepareUrl( T input );

}

次に、必要な入力を他の方法(コンストラクター)で実装クラスに渡す必要があります。このようにして、クラスのステートレスな性質が失われ、入力を変更するたびに、異なるコンストラクター引数を使用してクラスを再作成する必要があります。

class SchedulePageUrlGenerator implements UrlGenerator {

    public static final String QUERY_STRING_BASE = "?from=";

    private final String showingBaseUrl;
    private final LocalDate date;

    public SchedulePageUrlGenerator( String showingBaseUrl, LocalDate date ) {
        this.showingBaseUrl = showingBaseUrl;
        this.date = date;
    }

    @Override
    public String prepareUrl() {
        DateTimeFormatter fmt = DateTimeFormat.forPattern( "yyyy-MM-dd" );
        String dateStr = fmt.print( date );
        return showingBaseUrl + QUERY_STRING_BASE + dateStr;
    }

}

私のデザインには根本的な問題があるに違いないと思います。

4

3 に答える 3

5

私のデザインには根本的な問題があるに違いないと思います。

唯一間違っているのは、1つの引数のメソッドと0つの引数のメソッドを混同しようとしていることです。他の問題への扉を開かずに、Javaでそれを行うことはできません。

基本的に、3つの選択肢があります。

  • 現在のアプローチに固執しnull、Voidの場合を明示的に渡します。

  • Voidの場合を処理するために、インターフェイスに2番目の(引数なしの)メソッドを追加し、。を使用して1つの引数のメソッドを呼び出すようにしますnull。あなたのコードはwhenisnotに対処する必要がnullありTますVoidが、とにかくそうしました。

  • インターフェイスをリファクタリングして、1つはaを使用し、もう1つはを使用する2つの異なるインターフェイスを作成しString prepareUrl()String prepareUrl(T)前者を特殊なケースのクラスとして実装します。

個人的には、オプション2はオプション1よりもわずかに優れていますが、3番目のオプションはおそらく他の問題につながるでしょう。たとえば、2つのバリアントを持つ特定のメソッドは、型の空間全体にわたるポリモーフィックメソッド呼び出しの障害になりTます。

(Varargsは悪い考えです。なぜなら、それはおそらくあなたの問題にとって無意味である複数の議論への扉を開くからです。)

于 2012-08-29T13:42:42.093 に答える
2

問題は、SchedulePageUrlGenerator本当にであるかどうかですUrlGenerator。それが異なる議論をしているなら、私はそうではないと主張するでしょう。インターフェイスにオプションの引数がある場合は、呼び出し元のコードで次のようなことを行う必要があると思います。

// this is not a good pattern
if (urlGenerator instanceof SchedulePageUrlGenerator) {
    (SchedulePageUrlGenerator)urlGenerator.prepareUrl();
} else {
    urlGenerator.prepareUrl(...);
}

これはハックのようです。

とはいえ、インターフェイスにさらに多くのメソッドがあり、それだけが異なる場合は、への引数としてprepareUrl(...)渡すことに問題はありません。引数を生成する方法と、引数がそのような問題である理由を理解するには、呼び出しフレームワークをもっと見る必要があると思います。nullVoidprepareUrl(...)null

もう1つの方法は、インターフェイスにさらに多くのメソッドがある場合、引数の準備メソッドがある場合とない場合の両方を使用することです。

String prepareUrl( T input );
String prepareUrlNoInput();

UnsupportedOperationException次に、どちらがどの実装でサポートされているかに応じてスローできます。しかし、繰り返しになりますが、上記のステートメントのようなことをしなければならない場合はinstanceof if、議論の方が良いと思いますnull

于 2012-08-29T13:36:35.250 に答える
1

実装ごとに異なる数の引数を評価したいようです。

これに最も近いのは、varargsを使用することです。

interface UrlGenerator<T> {
    String prepareUrl(T... input );
}


// can use
System.out.println(new StaticUrlGenerator("url").prepareUrl());

//or
System.out.println(new StaticUrlGenerator("url").prepareUrl(null));
于 2012-08-29T13:36:34.860 に答える