勉強日記

チラ裏

GoF本 Facade

ねらい

  • 複数クラスからなるサブシステムに窓口を設け、簡単に使えるようにする

モチベーション

  • システムをサブシステムに小分けにすることで、複雑性を下げることができる
    • サブシステムはクラスと似ている
  • クライアント-サブシステム間や、サブクラス同士の依存を最小化したい
  • 単一の窓口オブジェクト、facadeを設けることでこれを実現する
  • facadeは高レベルなインタフェースを提供する
    • あまり細かなことはできないが、大抵はこれで充分
    • 使うのが簡単
  • 細かな操作を行いたい場合は、サブシステムを構成するクラス群を直接操作する
    • 強力でなんでもできる低レベルなインタフェース
    • 使うのが大変

つかいどころ

  • 複雑なサブシステムについて、簡潔なインターフェースを提供したい
    • 何でもできるのが使いやすいとは限らない
  • クライアントコードと、サブシステムを構成するクラス群との間に、多くの依存関係が存在する
    • Facadeを通してアクセスさせることで依存を切り離す
  • サブシステム間の依存関係を完結にしたい

登場人物

  • Facade
    • クライアントコードから要求を受け取る
    • 要求について、どのsubsystem classが責務を持っているか知っている
    • 適切なsubsytem classesに処理を委譲する
  • subsystem classes
    • サブシステムの機能を実装する
    • Facadeから委譲された仕事を全うする
    • Facadeのことは認知しない
      • Mediatorパターンとの大きな違い

結果

  • クライアントがサブシステムを利用するにあたり、直接利用するクラスが減り、使いやすくなる
  • クライアントとサブシステムとが疎結合になる
    • それぞれ独立して開発されていく場合はとくに重要
    • コンパイル時の依存性が減少するため、再コンパイルが減るのもうれしい
  • クライアントコードには、「簡単に使えること」と「何でもできること」のトレードオフを提供できる

実装にあたり考えるべきこと

  • クライアント-サブシステム間を疎結合にする
    • Facadeを抽象クラスにする
      • サブシステムの実装ごとにConcreteFacadeを用意
      • 挿げ替えるのが容易になる
        • クライアントはどのConcreteFacadeを使っているのか認知しない
    • Facadeオブジェクトにsubsystem classesのオブジェクトを集約させる
      • subsytem classesオブジェクトを挿げ替えることで、別実装に挿げ替えることができる
  • サブシステムを構成するクラス群にアクセシビリティを設ける
    • サブシステムとクラスとは似ている
    • サブシステムにとってのクラスは、クラスにとってのメンバに相当する
    • クラスを構成するメンバにアクセシビリティがあるように、
      サブシステムを構成するクラスにもアクセシビリティを設けることは有用である
    • Facadeクラスは当然"public"に属する
      • サブシステムの低レベルインターフェースを利用する際に、
        直接アクセスするsubsystem classesも"public"に属する

【補強】用例

  • 例) Laravelの\DBファサード
    • Facadeパターンを享受するケース: \DB::someOperation();
      • デフォルトのコネクションに処理を委譲する
      • \DBDatabaseManagerオブジェクトに処理を委譲しているので、DatabaseManagerがFacadeパターンにおけるFacadeクラスにあたる
      • Laravel用語的には
        \DBのクラスメソッドを呼び出しているかのようにDatabaseManagerインスタンスメソッドを呼び出せる」
        機能をFacadeと呼んでいる。言葉のずれがややこしい
    • サブシステムの構成クラスを直接操作するケース: $connection = \DB::connection('connection_name');
      • Connectionオブジェクトを取得し直接操作する。デフォルト以外のコネクションを使うときに呼び出す

関連するパターン

  • AbstractFactory
    • サブシステムを構成するオブジェクトを作らせる
      • 作ったオブジェクトをFacadeが集約する
  • Mediator
    • サブシステムを構成するクラス群において、スター型の依存構造をつくり、真ん中に陣取るヤツ。
      また、そのパターン
    • 既存のクラスの機能を抽象化するという点ではFacadeと似ている
    • 異なる点
      • Facade
        • クライアントとサブシステムとの間に立ち、リクエストを仲介する
        • サブシステムを構成するクラスは、Facadeの存在を知らない
      • Mediator
        • サブシステムを構成するクラス同士の連絡を仲介する
        • サブシステムを構成するクラスは、Mediatorの存在を知っている
  • Singleton
    • Facadeオブジェクトはふつう1つでよいのでSingletonにできる

英語

  • forgo
    • 諦める、控える
      • 何かを切り捨てる感じか
      • 納期の都合上、要求を取捨選択して要件を小さくするときとか