こんにちはecbeingでアーキテクトをやっている宮原です。
皆さんデザインパターンについてはどのくらいご存知でしょうか?
「かなり自信がある」という方も「名前は聞いたことあるけど・・・」という方もいると思います。
今日はそんなデザインパターンの中から「Facade」と「Mediator」を取り上げます。
FacadeとMediatorの類似性??
ある程度デザインパターンに詳しい方なら、「FacadeとMediatorは似ている」というタイトルを読んで『あれ、そうだったっけ?』となるかもしれません。
この考え方は自分が発想したものではありません。
下記に紹介する書籍「アジャイルソフトウェア開発の奥義(以下「アジャイル奥義本」)」の第15章に書かれている内容なのです。
www.amazon.co.jp
『15章:FacadeパターンとMediatorパターン』
この章で取り上げる2つのパターンの目的は共通して言える。
どちらのパターンも、ある種の方針*1をオブジェクトに強制する。
Facadeパターンは上から方針を強制し、Mediatorパターンは下から方針を強制する。Facadeパターンは視覚的にとらえることができる制約的な方法であるのに対し、Mediatorパターンは視覚的にとらえることはできない方法で方針を強制する。
(アジャイルソフトウェア開発の奥義 p.223 より)
この抜粋した文章を読んで、『うんまあそうだよね』という感想をもった方。
申し訳ありません。
当記事はこの抜粋文章をこのあと延々と説明をするだけの記事です。
得るものはないのでそっ閉じして下さい。
それ以外の『日本語は分かるが意味がわからん』という感想を持った方、あなた達こそがこの記事がターゲットとする読者の方々です。
是非最後までお付き合い下さい。
FacadeとMediatorとは
ではまずFacadeパターンとMediatorパターンのおさらいから始めましょう。
デザインパターンのバイブルとも言える書籍、「オブジェクト指向における再利用のためのデザインパターン(以下「デザパタ本」)」から両者の説明を抜粋します。
www.amazon.co.jp
Facade
サブシステム内に存在する複数のインタフェースに1つの統一インタフェースを与える。Facadeパターンはサブシステムの利用を用意にするための高レベルインタフェースを定義する。
(オブジェクト指向における再利用のためのデザインパターン p.197 より)
やや恣意的な例ですが、Subsystemクラス群とそれを使うClientクラス群があったとすると、Facadeが無い場合ClientとSubsystemの通信は以下のようになります。
全てのClientクラスが全てのSubsystemクラスに直接アクセスするため、クラス間の関連が非常に複雑になってしまっています。
そこでFacadeを導入して複雑な関連を単純化するのがFacadeパターンとなります。
Mediator
オブジェクト群の相互作用をカプセル化するオブジェクトを定義する。
Mediatorパターンは、オブジェクト同士がお互いを明示的に参照し合うことがないようにして、 結合度を低めることを促進する。
それにより、オブジェクトの相互作用を独立に変えることができるようになる。
(オブジェクト指向における再利用のためのデザインパターン p.291 より)
あるオブジェクト群が相互に通信する場合、
直接通信すると以下のようになります。
オブジェクトがそれぞれ通信するので、その通信経路はオブジェクトの数の階乗に比例してどんどん増加してしまいますが、Mediatorパターンを導入して全ての通信経路をMediator経由にすることで、通信経路の増加を抑えることが出来ます。
FacadeとMediatorとの関連
さてアジャイル奥義本では「ある種の方針をオブジェクトに強制する」と書かれていた両パターンですが、上記を見る限りどちらも「方針の強制」ようには書かれていません。
またMediatorとFacadeが似ているとも共通目的を持っているとも書かれていません。
実はデザパタ本には巻末にデザインパターン間の関連が図で表されているのですが、そこでもMediatorパターンとFacadeパターンに関連があるという描写はありません。
【デザインパターン間の関連(Facade部分)】
(オブジェクト指向における再利用のためのデザインパターン 巻末見返し より)
【デザインパターン間の関連(Mediator部分)】
(オブジェクト指向における再利用のためのデザインパターン 巻末見返し より)
それぞれのパターン構造
ではなぜ「アジャイル奥義本」ではこれらのパターンの共通目的として、「方針の強制」があると書かれていたのでしょうか?
それはそれぞれのパターンの構造に秘密があります。
Facadeパターンの構造
先程の説明で使用した下記の図を御覧ください。
ClientクラスとSubsystemクラスの全ての関連(=通信)がFacadeクラスに一度集約しています。
Facadeクラスに方針(例えば『Sub1はSub2の前にかならず呼ぶ』『全ての処理の最後にSub5を必ず呼ぶ』など )を記述することで、Clientクラスに方針を強制させることが出来ます。
この様に、かつてはシステムの複雑さの軽減のために使用されていたFacadeパターンですが、近年では「方針の強制」が使用目的の一つになっています。
Mediatorパターンの構造
ではMediatorパターンを見てみましょう。
Facadeの説明を読んだ後だとピンと来るかもしれません。
Mediatorクラスに通信が集約しているため、ここに方針を記述することで各Colleagueクラスに対して方針の強制を行うことが出来ます。
Facadeと同じくオブジェクト間の通信経路を単純化させるために使用されていたMediatorパターンが、今では「方針の強制」に利用されているのです。
明示的・暗示的
さてもう一度アジャイル奥義本からの抜粋を見てみましょう。
『15章:FacadeパターンとMediatorパターン』
この章で取り上げる2つのパターンの目的は共通して言える。
どちらのパターンも、ある種の方針をオブジェクトに強制する。
Facadeパターンは上から方針を強制し、Mediatorパターンは下から方針を強制する。Facadeパターンは視覚的にとらえることができる制約的な方法であるのに対し、Mediatorパターンは視覚的にとらえることはできない方法で方針を強制する。
(アジャイルソフトウェア開発の奥義 p.223 より)
『どちらのパターンも、ある種の方針をオブジェクトに強制する。』という部分については解説しました。
では、『Facadeパターンは視覚的にとらえることができる制約的な方法であるのに対し、Mediatorパターンは視覚的にとらえることはできない方法で方針を強制する。』という文はどういう意味でしょう?
下記のFacadeパターンの図を御覧ください。
上の図のClientクラスの一つをUserクラスとして書き直してみました。
Userから見た時FacadeクラスはUserクラスと直接関連があります。
Userクラスと直接通信するFacadeクラスで方針の強制が行われているため、この強制を「視覚的にとらえることが出来る」強制、すなわち明示的な強制であると表現しているのです。
一方Mediatorクラスですが、ここにUserクラスを追加してみましょう。
見てお分かりの通りUserからMediatorに直接通信はありません。
Userクラスから隠されているMediatorクラスによって方針の強制が行われているため、この強制を「視覚的にとらえることができない」強制、すなわち暗示的な強制であるとアジャイル奥義本では定義しているのです。
この様にそれぞれのパターンは構造により一方は「明示的(視覚的にとらえることが出来る)」もう一方は「暗示的(視覚的にとらえることができない)」とアジャイル奥義本では表現されているのです。
Mediatorの汎用化
さて少し話を変えますが、下記のMediatorパターンの図はデザパタ本での表現をもとにしています。
デザパタ本でのMediatorパターン
この図の中にはColleague(カリグー)というオブジェクトがあります。
Colleagueとは「同僚」という意味で、同じクラスや似たクラス(同じ継承元を持つなど)のインスタンスを想定しています。
つまりデザパタ本におけるMediatorパターンとは
- 「似たような」
- 「オブジェクトが」
- 「相互に」
- 「通信を行う場合」
- 「Mediatorクラスを経由する」
というパターンということになります。
一方アジャイル奥義本にはColleagueクラスは出てきません。
アジャイル奥義本でのMediatorパターン
Colleagueクラスは存在せず、特に共通点が無いクラスの通信の間にMediatorがいるのみです。
また、相互通信である必要も特になく一方的な通信でも構わないという構造になっています。
つまりアジャイル奥義本では
「似たような」- 「オブジェクトが」
「相互に」- 「通信を行う場合」
- 「Mediatorクラスを経由する」
というパターンになっているということです。
この様に汎用化されたMediatorパターンこそが現代でのMediatorパターンの主な使用方法となっており、その使用目的も通信の複雑度を下げることよりも、方針の強制を行うことが主目的となっています。
FacadeとMediatorの類似性!!
ではMediatorの汎用化の前提に立ち、あるアーキテクチャにFacadeパターンとMediatorパターンを適用した図を見てみましょう。
デザインパターン適用前
Facadeパターン適用
Mediatorパターン適用
このようにFacadeパターンとMediatorパターンは、それぞれの核となるクラスをアーキテクチャ内のどこに配置するかだけが異なる、非常によく似たパターンであることがわかります。
まとめ
ということで「アジャイルソフトウェア開発の奥義」に書いてあるとおり、
- FacadeとMediatorはどちらも「方針を強制」させるパターン
- Facadeは明示的に、Mediatorは暗示的に強制を行う
ということをご理解いただけたでしょうか?
FacadeパターンはDB操作やネットワーク通信など、多くのクラスを複雑に使用することが要求されるような際に利用すると良いと思います。
またMediatorは書き込み処理の途中でテキストをフォーマットしたり、通信の途中で文字コードを変換するなど必要だけれど、トップレベルの処理からは隠したい場合に利用するなどが良いでしょう。
Mediatorパターンを「似たようなオブジェクト間の相互通信を仲介するパターン」と捉えると、我々が手掛ける業務プログラムに「似たようなオブジェクト間の相互通信」のシチュエーションがそれほど多く発生しないため、あまり使用する機会がありません。
しかし視点を変え、暗示的に方針を強制させるパターンと捉えると、意外に多くの場面で使用することが出来るかもしれません。
視点を変えると意外な使い道が見つかるかもしれない、というお話でした。
ecbeingでは異なる視点で物事を捉える人材を募集しています!!
careers.ecbeing.tech
*1:ここで使われる「方針」とは、「DBをオープンしたらクローズする」「入出力の文字コードはUTF-8を使用する」などプログラム上でのルールのことです。