広告

Java : Facade パターン (図解/デザインパターン)

Facade パターンとは、GoF によって定義されたデザインパターンの1つです。
複雑な操作が必要となるサブシステムに対して、シンプルなインタフェースを提供します。

本記事では、Facade パターンを Java のコード付きで解説していきます。


デザインパターン(GoF) 関連記事

図解/デザインパターン一覧

概要

Facade パターンあるいは Façade パターン(ファサード・パターン)とは、GoF(Gang of Four; 4人のギャングたち)によって定義された、コンピュータソフトウェアのデザインパターンの1つである。Facade(ファサード)とは「建物の正面」を意味する。異なるサブシステムを単純な操作だけを持ったFacadeクラスで結び、サブシステム間の独立性を高める事を目的とする。

Facade パターンとは、

  • 複雑な操作や連携が必要となるクラス群 (サブシステム、モジュールなど) があり
  • 上記に対して、使いやすいシンプルなインタフェースを提供する

という目的のための設計です。

もっと簡単にいうと、

  • 複雑な処理をまとめる

ということです。
サブルーチン の考え方をもう少し広げた感じでしょうか。

Facade は、日本語的に発音すると「ファサード」となります。
意味は「建物の正面」ですね。


【Facade パターンのイメージ】

イメージ図1

クライアントは とあるデータを出力 したいとします。
しかし、そのためには クラスA, B, C, D を使う必要があります。

例えば …

  1. クラスA で元となるデータを取得
  2. それを クラスB で変換
  3. さらに クラスC で加工
  4. 最後に クラスD で出力

という工程が必要だとしましょう。

欲しいのは、最後の結果だけ です。
しかし、そのためには クラスA, B, C, D の使い方をプログラマーが 理解する必要 があります。

1回だけしか使わない、自分だけしか使わない、というのであればそれもよいかもしれません。
しかし、そうでなけば手間ですし工数もかかります。


イメージ図2

「ファサード」クラスは、クラスA, B, C, D をクライアントから 隠蔽(カプセル化) します。

クライアントは、「ファサード」クラスの シンプル なインタフェースを呼び出すだけです。
クラスA, B, C, D を知る必要はありません。それはコーディングの時間短縮にもつながるでしょう。

これが、Facade パターンのメリットになります。

オブジェクト指向に限らず、プログラミングにおいては、わりと自然な考え方なのかな … と思います。

関連記事:


クラス図とシーケンス図

クラス図1

シーケンス図1

上の図は、Facade パターンの一般的なクラス図とシーケンス図です。

依存関係は、

  • Facade → ClassA, B, C

です。逆はない のでご注意ください。

それでは、このクラス図をそのままコードにしてみましょう。

まずは ClassA, B, C です。

  1. ClassA で値を取得
  2. ClassB で値を変換
  3. ClassC で値を出力

という流れになります。

public class ClassA {
    public String getText() {
        return "facade pattern!";
    }
}

public class ClassB {
    public String convert(String text) {
        return text.toUpperCase();
    }
}

public class ClassC {
    public void print(String text) {
        System.out.println(text);
    }
}

次に、Facade クラスです。

public class Facade {
    private final ClassA a = new ClassA();
    private final ClassB b = new ClassB();
    private final ClassC c = new ClassC();

    public void operate() {
        final var text1 = a.getText();
        final var text2 = b.convert(text1);
        c.print(text2);
    }
}

それでは、これらのクラスを使ってみましょう。
といっても、Facade クラスのシンプルなメソッドを呼び出すだけです。

final var facade = new Facade();
facade.operate();

// 結果
// ↓
//FACADE PATTERN!

結果も問題なしですね。
"facade pattern!" という文字列が、大文字に変換されてからコンソールに出力されました。


具体的な例

もう少し具体的な例も見てみましょう。
Webページを表示するブラウザを考えてみます。

クラス図2

Webページを表示するためには、

  • HTMLドキュメントの解析 (HtmlParser)
    上記の解析結果 (HtmlItem)
  • 画像の読み込み (ImageReader)
  • 動画の読み込み (VideoReader)

が最低限必要になるとしましょう。

あと、例を簡単にするために、画像と動画はそれぞれ1つしか読み込めないとします。

クライアントとしては、

  • HTMLドキュメントの解析
  • 画像・動画の読み込み

といった細かいことには興味がありません。
とにかく「Webページ」を 表示したいだけ です。

それでは Facade パターンを使ってコードを書いてみましょう。

HtmlParser クラスは、HTMLドキュメントを解析して HtmlItem オブジェクトを生成します。
(HtmlItem は「レコードクラス」です)

public class HtmlParser {
    public HtmlItem parse(String html) {

        ... 解析処理は省略 ...

        return new HtmlItem(... 省略 ...);
    }
}

public record HtmlItem(String text, String image, String video) {
}

ImageReader クラスは画像を読み込みます。
ここでは、実際の読み込み処理ではなく、代わりにテキストを表示させます。

public class ImageReader {
    public void read(String image) {
        System.out.println("画像読み込み OK : " + image);
    }
}

VideoReader クラスは動画を読み込みます。
こちらも、実際の読み込み処理ではなく、代わりにテキストを表示させます。

public class VideoReader {
    public void read(String video) {
        System.out.println("動画読み込み OK : " + video);
    }
}

最後に WebPageFacade クラスです。
今までのクラスを使って、Webページを表示させます。
(といっても、非常に簡易的なテキストでの表示です)

public class WebPageFacade {
    public void show(String html) {
        System.out.println("-- WebPage show --");

        final var parser = new HtmlParser();
        final var item = parser.parse(html);

        final var imageReader = new ImageReader();
        imageReader.read(item.image());

        final var videoReader = new VideoReader();
        videoReader.read(item.video());

        System.out.println("テキスト : " + item.text());
    }
}

それでは、実際に WebPageFacade クラスを使ってみましょう。
show メソッドに HTMLドキュメントを指定します。

final var html = """
        <html>
        <body>
        <img src="image.jpg"></img>
        <video controls src="video.mp4"></video>
        Hello, World!
        </body>
        </html>
        """;

final var facade = new WebPageFacade();
facade.show(html);

// 結果
// ↓
//-- WebPage show --
//画像読み込み OK : image.jpg
//動画読み込み OK : video.mp4
//テキスト : Hello, World!

テキストによる簡易的なものですが、無事に Webページが表示できました。

WebPageFacade を使うことにより、

  • HtmlParser
  • HtmlItem
  • ImageReader
  • VideoReader

といったクラスを意識しなくて済みます。
つまり、これらのクラスを 隠蔽(カプセル化) したわけですね。

まとめ

Facade パターンとは、

  • 複雑な操作や連携が必要となるクラス群 (サブシステム、モジュールなど) があり
  • 上記に対して、使いやすいシンプルなインタフェースを提供する

という目的のための設計です。

オブジェクト指向に限らず、プログラミングにおいては、わりと自然な考え方なのかな … と思います。
ぜひ有効に活用していきたいですね。


関連記事

ページの先頭へ