1

前提:私のプロジェクトでは、それぞれ Request と Response を定義する 2 つの一般的に型指定されたインターフェイスがあります。リクエストはレスポンスを生成するために処理されるため、すべてのレスポンスはリクエストに基づいて作成されます。Processor インターフェースは、要求を処理して、対応する応答を作成します。

コード:リクエストとレスポンスのインターフェースは次のとおりです。

interface Request<T1>

interface Response<T2>

T2ここで、とはそれぞれ、T1一般的なリクエストとレスポンスのタイプを表します (わかりやすくするために、意図的に別の名前で呼んでいます)。

ここで、T2要求であり、T1応答であるため、上記のコードは次のように展開されます。

interface Request<T1 extends Response>

interface Response<T2 extends Request>

以下に注意してください: リクエストとレスポンスのインターフェースは継承関係を共有しません。

ここで、Request インターフェースを考えてみましょう。Response は再び型指定され、要求から構築された応答は元の要求タイプに関連付けられるため、上記のコードは次のように進化します。

interface Request<T1 extends Response<? extends Request<T1>>>

interface Response<T2 extends Request<? extends Response<T2>>

現在、プロセッサ インターフェイスは次のように定義されています。

interface Processor<R1 extends Request<R2>, R2 extends Response<R1>> {
    R2 process(R1 request);
}

具体的なクラス:

リクエストの実装:

class ConcreteRequest implements Request<ConcreteResponse> {
    ConcreteResponse response;
    ...`
}

レスポンスの実装:

class ConcreteResponse implements Response<ConcreteRequest> {
    ConcreteRequest request;
    ...
}

プロセッサの実装:

class ConcreteProcessor implements Processor<ConcreteRequest, ConcreteResponse> {
    ConcreteResponse process(ConcreteRequest request) {
    ...
    }
}

質問:上記のコードは過度に設計されていますか? 補完的な入出力オブジェクトのタプルを表す簡単な方法はありますか?

4

3 に答える 3

1

タイプ定義でRequestとをリンクする必要はないと思います。Responseそれらはによって結ばれていProcessorます。のようなものではありません

interface Requestable {
    ...
}

class Request<T extends Requestable> {
    ...
}

class Response<T extends Requestable> {
    ...
}

class Processor<T extends Requestable> {
    Response<T> process(Request<T> request) {
        ...
    }
}

十分な ?実際、ジェネリックが必要かどうかはわかりません。

于 2013-02-01T11:08:54.140 に答える
1

私があなたの質問を完全に誤解していない限り、この種の問題にジェネリックを使用しないでください。ポリモーフィズムおよび/または構成を使用する方がはるかに適切です。たとえば、リクエストのコピーをレスポンスに統合する必要がある場合 (ほとんど必要ではありませんが考えられます)、レスポンス クラスにリクエスト オブジェクトへの参照を追加できます。

技術的には、オブジェクトへのこの参照Requestは型を使用して定義できます。Requestただし、これは常にオブジェクト (基本クラスまたは派生サブクラス) であり、応答のインスタンス化ごとに変更される可能性のある任意のクラスではないため、これを行うべきではありません。

参照される各オブジェクトの型がまったく異なる場合 (たとえば、 aList <String>または a : aとオブジェクトList<Request>の間にサブクラス化の関係がない場合)、または 1 つ以上の新しいオブジェクトを定義しているためポリモーフィズムの使用が十分でない場合は、generic を使用します。スーパークラスには存在しないサブクラスの仮想関数。StringRequest

a が aを生成するように処理されるため、 aResponseに基づいて a を構築することは間違いなく進むべき道ではなく、現在のインターフェイスはその証拠です。RequestRequestResponseProcessor

于 2013-02-01T08:08:20.260 に答える
0

汎用化された要求/応答 (または、少なくとも要求) を使用すると便利なユース ケースが 1 つあります。リクエストがレスポンス タイプを含むように生成されている場合、次の呼び出しは「タイプセーフ」です。

public <messy define of T> T sendRequest(Request<T> request)  

これで、そのメソッドのユーザーは、「タイプセーフ」な要求と応答の呼び出しを確認できます。そのメソッドの実装はおそらく応答を T にキャストする必要があるため、これを「タイプセーフ」と呼んでいます。理論的には ClassCastExceptions が発生する可能性がありますが、ほとんどの場合、アプリケーション ロジック エラーと見なされます。

Request/Response の実際のフィールドをその他のフィールドに配置することはせず、「タイプセーフ」な要求と応答の呼び出しに一般的な型情報を使用するだけです。

于 2015-05-27T11:04:00.740 に答える