1

RequestHandler クラスと RequestListener クラスがあります。RequestHandler は RequestListener を作成し、それ自体への参照を渡します。次に、RequestListener は RequestHandler のメソッドを呼び出して、処理時にさまざまなタイプのリクエストを処理します (例: handleTypeARequest()、handleTypeBRequest() など)。残念ながら、RequestHandler は RequestListener (例: processNextRequest()) のメソッドも呼び出すため、循環依存関係があります。

class RequestHandler {
   RequestListener requestListener;
   ...
}

class RequestListener {
   RequestHandler requestHandler;
   ...
}

これは、2 つの間の結合がより緊密であることを意味し、一般的にはコードの匂いと見なされます。

1 つの解決策は、異なるメソッドではなく、異なるオブジェクトを使用して各リクエストをカプセル化することです。RequestListener は、プロンプトが表示されたときにリクエストを処理し、そのリクエストに対して何らかのタイプの Request オブジェクトを返すことができます。残念ながら、私はこのアプローチがあまり好きではありません。その理由の 1 つは、より多くのオブジェクトとクラスの複雑さが増したためであり、もう 1 つはパフォーマンスの問題 (ここで重要です) のためです。RequestHandler で handleXXXRequest() メソッドを直接呼び出すと、一連のオブジェクトを作成し、必要になるまでそれらをバッファリングするためにスタックを維持するよりもはるかに高速です。

この問題に対する他の解決策はありますか?また、それは本当に問題なのでしょうか?

4

3 に答える 3

3

ええ、これは本当に問題ですか?

あなたが言ったかのように、親子参照に問題があり、両方が相互に参照を保持しています。ここに本当に問題があるとは思いません。

于 2010-07-28T20:12:49.477 に答える
1

プログラミング言語では、クラスを前方宣言できる可能性が高く、構文エラー部分を回避できます。

C++ の場合、次のようにします。

class RequestListener;

class RequestHandler {
    RequestListener *requestListener;
    /* ... */
}

class RequestListener {
    RequestHandler *requestHandler;
    /* ... */
}

ただし、オブジェクト自体を再帰的にネストしようとすると問題が発生することに注意してください (無限に大きな構造が得られるため)。

class RequestListener;

class RequestHandler {
    RequestListener requestListener;
        // the compiler will complain about an incomplete type here
    /* ... */
}

class RequestListener {
    RequestHandler requestHandler;
    /* ... */
}

オブジェクトがお互いを含むのではなく、お互いを参照したいだけなので、問題ありません。

于 2010-07-28T20:14:22.003 に答える
0

イベントを使用すると、クラスを明示的に参照しなくても、特定の状態の変化について他のオブジェクトに通知できます。

class RequestListener
{
    public event EventHandler<RequestReceivedEventArgs> RequestReceived;

    public void ProcessNextRequest(object sender, RequestHandledEventArgs e)
    {
        // Process next request.
    }
}

class RequestDispatcher
{
    public event EventHandler<RequestHandledEventArgs> RequestHandled;

    public void DispatchRequest(object sender, RequestReceivedEventArgs e)
    {
        // Invoke correct RequestHandler class/method.

        // Raise RequestHandled event when request handler has finished.
    }
}

var listener = new RequestListener();
var dispatcher = new RequestDispatcher();

// Subscribe to each other's events.
listener.RequestReceived += dispatcher.DispatchRequest;
dispatcher.RequestHandled += listener.ProcessNextRequest;

上記の C# の例は、.NET Framework のガイドラインに従っているため、非常に冗長ですが、クラス間の分離を示す必要があります。RequestDispatcherまた、リスナーに処理させるのではなく、正しいハンドラーの呼び出しを担当するクラスも導入しました。

追加のクラスを作成したくない場合は、このモデルを本当に必要なものだけに分解できます。たとえば、リスナーTypeARequestReceivedでイベントを公開できます。TypeBRequestReceivedその後、リクエスト ハンドラー メソッドはこれらのイベントに直接サブスクライブできます。

于 2010-07-29T12:33:12.627 に答える