}これらのメソッドから呼び出される会員側のメソッド(#calculateRentalFeeForCD()および#calculateRentalFeeForVideo())は、やはりそれぞれのサブクラス(CommonMemberおよびGoldMember)でオーバーライドされて実装されます。これでめでたく(オブジェクトの種別を判別するための)switch文が完全に排除されたことになります。ゴールド会員がDVDを借りる場合の料金計算}「ダブル・ディスパッチ」という名前は"Dispatch"(ここでは「分配する」とか「選択する」とかいったニュアンスで使われています)を2回行うというところに由来しています。この例での最初の"Dispatch"はRentalShop#calculateRentalFee()メソッド中でのItem#calculateRentalFee()の呼び出しの際に言語処理系によって行われます(実際の商品種別によってサブクラスのいずれかの#calculateRentalFee()メソッドが選択されて実行されます)。商品の各々のサブクラスでオーバーライドされた#calculateRentalFee()メソッド中で、今度はMember#calculateRentalFeeForCD()かMember#calculateRentalFeeForDVD()のいずれかが呼び出されて2回目の"Dispatch"が実行されます(これも実際の会員種別毎のサブクラスでオーバーライドされた#calculateRentalFeeForCD()か#calculateRentalFeeForDVD()のいずれかが選択されて実行されます)。ダブル・ディスパッチは、この例のように、「別々のクラス階層に含まれる二種類のオブジェクトの組み合わせによって処理の内容(振る舞い)を変える必要がある」といった状況で使われます。モデル上、一見複雑な形になってしまったように思えますが、この構造は新たに会員種別が増えたりするような場合に有利です。「法人会員」や「特別会員」、「ファミリー会員」などといった新しい会員種別を追加することを想像してみてください。そのような場合、それぞれの会員種別を表わす新規のクラスがMemberクラスのサブクラスとして追加されますが、既存のクラスやメソッドにはいっさい追加・変更が加わらないということが判るでしょう。逆に、新たな商品種別が追加されるような場合には、既存のクラスに手が入ることになります。※クリックして拡大表示この場合、Bookクラスの追加と、MemberクラスおよびそのすべてのサブクラスにBook用の料金計算メソッドの追加が必要になります。既存のクラスにメソッドが追加されてはいますが、それでも、既存のメソッドに対してコードの変更が入ることはありません。会員種別よりも商品種別の方が増えやすいなら、会員種別と商品種別との間のディスパッチの方向を逆転させた設計にすることを検討してみるべきでしょう。ダブル・ディスパッチの欠点(注意点)は、メッセージ呼び出しのオーバー・ヘッドとクラス数、メソッド数の増加でしょう。メソッドが定義されなくてはならなくなります。※クリックして拡大表示ここではContainerとComponentというクラスの間に1:多の双方向関連が張られています。双方向関連なので、あるContainerインスタンス(aContainer)のcomponentsとして参照されているすべてのComponentインスタンスは、必ずcontainerとしてaContainerを参照していなければなりません(そのどちらか片方しか成り立たないという状況は許されません)。このような双方向参照を保証するコードの実装例を以下に示します(単純化のため、マルチ・スレッドやエラー処理等への対処は省略されています)。}このコードでは、Container#addComponent()メソッド、Container#removeComponent()メソッド、および、Component#setContainer()メソッドが、それぞれ自分自身(this)を引数として相互に呼び出しあっています(つまり形式としてダブル・ディスパッチになっているわけです)。若干コードが複雑で追いにくいのですが、Container#addComponent()でコンポーネントを追加しても、Component#setContainer()でコンテナを設定しても、どちらも同じ状況に落ち着くようになっています。おわりに以上、オブジェクト指向プログラミングでの典型的なコーディング・テクニックのひとつであるダブル・ディスパッチについて、Javaでの実装コード例を示しながら解説しました。ダブル・ディスパッチはオブジェクト指向言語の特徴のひとつであるポリモルフィズム(多相性)を上手に利用した設計/実装テクニックです。2つのオブジェクトの具体的な種別の組合せ毎にロジックが異なるような処理の実装や、2つのオブジェクト間で維持しなくてはならない制約を保証したい場合などに有効です。「デザイン・パターン」を読んだことがある人は、ここで紹介したダブル・ディスパッチとよく似たやり方を既に目にしているハズです。Visitorパターンなどですね。GoFのVisitorパターンもダブル・ディスパッチの応用例のひとつと考えることができます。ダブル・ディスパッチはいろいろと応用範囲の広い基本的なイディオムですが、前述したように利点ばかりではなく欠点もあります。いった利点・欠点のトレード・オフをしっかり考慮した上で「ここだ!」という個所(ツボ)に「びしっ!」と適用できるようなプログラマになりたいものですね。この記事が何らかのお役に立ちましたら幸いです...。毎週火曜日に前週のまとめコンテンツがお送りいたします。25万人ものシニアデベロッパーのコミュニティーにぜひご参加ください。サンプルを見るあなたのメールアドレスはこちら国を選んでください。プライバシーポリシーに従って私の個人情報を扱うことに同意します。登録するとさまざまなことができます。アカウント登録をしてInfoQをお楽しみください。あなたの意見をお聞かせください。毎週火曜日に前週のまとめコンテンツがお送りいたします。25万人ものシニアデベロッパーのコミュニティーにぜひご参加ください。サンプルを見る様々なイノベーターとアーリーアダプターがお送りするテクノロジーの概要を見る。自分がまだ知らないことに気づいていないと知るあなたが興味のあるトピックスをいつでも最新な情報に。あなたのメールアドレスはこちら国を選んでください。プライバシーポリシーに従って私の個人情報を扱うことに同意します。よい世界へ私たちが暮らす世界を大切に思い、よりよいものにしたいと考えています。人のためのソフトウェア開発を加速し私たちのミッションを実現することで、この思いを成し遂げようとしています。私たちは利益の1%をさまざまな慈善団体に寄付しています。会社として、また従業員として、そうしたことの価値を強く信じているからです。with.プライバシーBTあなたのプロファイルは最新ですか?プロフィールを確認してアップデートしてください。アドレス*Eメールを変更すると確認のメールが配信されます。会社名:現在の会社名をご入力ください。Other組織規模:現在の組織規模をご入力ください。2,501+国:現在の国を設定してください。Zimbabwe都道府県:現在の都道府県に設定してください。次の都道府県にアップデートする:ニュースレターを購読しますか?インダストリーメールを購読しますか?本Eメールに登録すると、以前より関心のあったトピックの関連情報をお送りする場合がございます。詳細はこちらのプライバシーポリシーをご覧ください。newsletter?新しいメールアドレスに確認用のメールを送信します。このポップアップ画面は自動的に閉じられます。