デザインパターンを勉強してみる--第2回 Facadeパターン--


Facade(ファサード)パターンとは

どもども。ここではFacadeパターンを学ぼうと思います。

突然ですが、皆さんカレーは好きですか?自分で作ったりしますか?

カレーの作り方も家によってさまざま。。
料理の手順が違ければ、隠し味も違ったりしますよね!
うちの父は酢と飲むヨーグルトを最近使ってました。(自分的には意外だったんですが、
酸っぱいものを加えるとカレーの味から角がとれてまろやかになるとのこと。実際その通りでした。)

さて、カレーも自分でうまく作れればいいですが、
失敗したものを家の夕飯で出したりしては目も当てられません。
それならいっそのこと、他の家族に作ってもらったほうがよほどマシではないですか?

今回学習するFacadeパターンも、「自分でやるより任せた方が」って発想のパターンです。

サンプルケース

ではカレー作りを例にとり説明していきます。
その前に調理手順のクラスを用意します。

・1:野菜を切る

ToCutVegetables.java
public class ToCutVegetables {
  public void exec () {
    System.out.println("1:野菜を切ります");
  }
}

・2:肉を切る

ToCutMeat.java
public class ToCutMeat {
  public void exec () {
    System.out.println("2:肉を切ります");
  }
}

・3:野菜と肉を炒める

ToFryVgtblsAndMeat.java
public class ToFryVgtblsAndMeat {
  public void exec () {
    System.out.println("3:野菜と肉を炒めます");
  }
}

・4:ルーを入れる

ToPutRoux.java
public class ToPutRoux {
  public void exec () {
    System.out.println("4:ルーを入れます");
  }
}

・5:隠し味にヨーグルト

ToPutYoghurt.java
public class ToPutYoghurt {
  public void exec () {
    System.out.println("5:隠し味にヨーグルトを入れます");
  }
}

・6:水を入れて煮る

ToBoilAfterAddingWater.java
public class ToBoilAfterAddingWater {
  public void exec () {
    System.out.println("6:水を入れて煮ます");
  }
}

以上が調理手順になります。

ではここからが本題。
例えばある家の息子が、夕食にカレーを作ろうとしますよね。
しかしこやつ、いまいち作り方がわかってないのです。
隠し味のヨーグルトを忘れているのです。(私的にはNG)

・息子

Son.java
public class Son {
  public static void main(String[] args) {

    // カレーを作ります。
    // 1:野菜を切ります。
    (new ToCutVegetables()).exec();

    // 2:肉を切ります
    (new ToCutMeat()).exec();

    // 3:野菜と肉を炒めます
    (new ToFryVgtblsAndMeat()).exec();

    // 4:ルーを入れます
    (new ToPutRoux()).exec();

    // 5:隠し味にヨーグルトを入れます
    // (入れてない)

    // 6:水を入れて煮ます
    (new ToBoilAfterAddingWater()).exec();
  }
}

見て分かるように、息子は調理手順のメソッドを呼び出し
調理をこなしていきますが、肝心の隠し味を入れ忘れています。

でも、母親は違います。
・母

Mother.java
public class Mother {
  // カレーを作ります。
  public void makeCurry() {
    // 1:野菜を切ります。
    (new ToCutVegetables()).exec();

    // 2:肉を切ります
    (new ToCutMeat()).exec();

    // 3:野菜と肉を炒めます
    (new ToFryVgtblsAndMeat()).exec();

    // 4:ルーを入れます
    (new ToPutRoux()).exec();

    /** 5:隠し味にヨーグルトを入れます(これがなくちゃ!) **/
    (new ToPutYoghurt()).exec();

    // 6:水を入れて煮ます
    (new ToBoilAfterAddingWater()).exec();
  }
}

makeCurryメソッドを見ると、
きっちり5番目で隠し味を入れるメソッドを実行してくれましたね。

「これ、もう母親につくってもらったらww」

この発想がFacadeパターン!!

・息子

Son.java
public class Son {
  public static void main(String[] args) {
    // 母に頼んでカレーを作ってもらいます
    new Mother().makeCurry();
  }
}

母のmakeCurryメソッドを呼ぶことで、
完璧なカレーが出来上がります。

-実行結果-

1:野菜を切ります
2:肉を切ります
3:野菜と肉を炒めます
4:ルーを入れます
5:隠し味にヨーグルトを入れます
6:水を入れて煮ます

まとめ

要は、facadeパターンとは「各クラスのメソッドをまとめて実行しなければならない時に、
まとめて一括で実行できる、窓口となるクラスを用意するパターン」なのです。(サンプルだと母がそれ。)

今回の各調理手順クラスのメソッドも全て呼び出さないと
カレーが出来ませんが、そういう「全てのクラスの処理を呼ばないと意味がない」ような場合に
便利なパターンです。窓口クラスのメソッドを実行するだけでいいんですから。
また、呼び出す順序にルールがあるなら窓口のクラスの中で順に呼ぶようにすればよいです。

私もコーディングしていると、「いくつもメソッド作ったけど、こいつらまとめて呼ばないと
意味ないんだよな。。」って状況にしばしば出会うので、使いどころの多そうなパターンかと思います。
まとめて実行できるようにしておけば、後でコーディングする人達も助かるでしょう。

(ちなみに、facadeとはフランス語を語源とする単語で「建物の正面」という意味です。)

次回

Compositeパターン。。かな?