私の質問は、可能な限り拡張可能な方法で、さまざまなメッセージに対してさまざまな動作を実装することです。私は訪問者のパターンを認識しており、二重ディスパッチを認識していますが、私を満足させる解決策を見つけられないようです(少なくともJavaの制限内ではありません)。
私の状況は次のとおりです。
私はメッセージの階層を持っています:
およびルーター インターフェイスの階層。それぞれが独自のメッセージ タイプのルート メソッドを定義します。
私はこれに似たものを実装したいと思います:
特定のメッセージをルーティングする機能を追加および削除したり、特定のメッセージのルーティング戦略を簡単に変更したりできます。
問題は、やりたくないメッセージをスイッチキャストしないと、インターフェースのそれぞれの機能を選択できないことです。
CompositeRouter comp = new AllRouter(...//new Router instances);
MessageBase msg = new DerivedMessage();
msg.process(comp);
オーバーロードを選択するJavaにつながります<runtime message-type>.process(Router)
これは、実行時にそれぞれのルーター オブジェクトに対して呼び出されます。そのため、コンパイル時に process() への正しい呼び出しを選択できないようです。その逆もできないので、comp.route(msg)
に解決され<dynamic router-type>.route(MessageBase)
ます。
CompositeRouter から適切なメソッドを選択するビジターを作成することもできますが、そのためには、事前にすべての MessageTypes に対して定義されたそれぞれの route-Methods を使用してビジター インターフェイスを定義する必要があります。新しい DerivedMessage を追加するたびに、訪問者を書き換える必要があります。
Message と Router の両方が拡張可能になるようにこれを実装する方法はありますか、それとも現在の Java 機能では絶望的ですか?
編集1:
Router
私が言及するのを忘れていたのは、 -hierarchyとほとんど同じである他の 4 つまたは 5 つの状況があるということです。そのため、ランタイム コストが心配なので、メソッド ルックアップのリフレクションは避けたいと思います。
コメントへの対応:
@bot の提案に関する @aruisdante の仮定は正しいです。route(MessageBase) をオーバーライドすると、MessageBase のランタイム タイプが失われるため、オーバーライドできません。
@aruisdanteと@geceo:私はそれができることを知っています-これは「スイッチキャスティング」で意味したことです(MessageBaseにはMessageTypeフィールドがあります)-しかし、コードには11の実際のメッセージクラスと〜6の場所が必要です、したがって、それはメンテナンスの面だけでなく、実装の面でも大きな苦痛になるでしょう。