メインコンテンツへ移動

デザインパターン - ファサードパターン(Facade Pattern)

無料2015-03-07#Design_Pattern#外观模式#Facade Pattern

ファサードパターンは、複雑なサブシステムに対してシンプルで使いやすい高レベルインターフェースを提供するために使用されます。あるサブシステムで簡単な機能を実装するために多くの低レベルコンポーネントを呼び出す必要があると感じた場合、ファサードパターンが役立ちます。

no_mkd

一.ファサードパターンとは?

簡単に言えば、ファサードパターンはインターフェースを簡素化するために使用されます。

通常、サブシステムが使いにくいと感じるのは、それが提供する外部インターフェースが低レベルコンポーネントに近づすぎて、不便に感じるからです。

内部の詳細を知る必要はなく、「ワンボタンで完了」する機能が欲しいだけです。サブシステムのメソッドを 1 つ呼び出すだけで、画像の前処理を代わりに実行してくれます。グレースケール化メソッド、画像強調アルゴリズム、ノイズ処理メソッドなどを自分で 1 つずつ呼び出して前処理を実現する必要はありません。

サブシステムが提供するインターフェースが低レベルコンポーネントに近づすぎている場合、使いにくいだけでなく、サブシステムのカプセル化も損なわれます(サブシステムを呼び出すために、その各低レベルコンポーネントについて理解する必要があり、知らなくてもよい詳細まで知ることになってしまいます。。)

二.例を挙げる

カプセル化された古い洗濯機があると仮定します。以下の外部インターフェースを提供しています:

package FacadePattern;

/**

  • @author ayqy

  • 洗濯機インターフェースの定義 / public interface Washer { /

    • 共通部分
    • */ //電源に接続 public abstract boolean connectToPower();

    /*

    • 洗濯部分
    • */ //左側の洗濯槽を開く public abstract void openLeftSide(); //給水口を開く public abstract void openWaterHole(); //給水開始 public abstract void startWaterInjection(); //給水停止 public abstract void stopWaterInjection(); //左側の洗濯槽の回転開始 public abstract void startWashing(); //左側の洗濯槽の回転停止 public abstract void stopWashing();

    /*

    • 脱水部分
    • */ //右側の脱水槽を開く public abstract void openRightSide(); //右側の脱水槽の回転開始 public abstract void startDewatering(); //右側の脱水槽の回転停止 public abstract void stopDewatering();

    /*

    • 排水部分は省略。。
    • */ }

仕方がありません。これは本当に古すぎて、現代の生活には満足できません。しかし、新しい自動化洗濯機を買う余裕はないので、半自動の洗濯機に変えて、浮いた時間でコードを書く必要があります。。まず、古い洗濯機でどのように洗濯するかを見てみましょう:

package FacadePattern;

/**

  • @author ayqy

  • 古い洗濯機で洗濯する */ public class Washing implements Washer{

    public static void main(String[] args) { //洗濯機オブジェクトの作成 Washer washer = new Washing(); //電源に接続 if(washer.connectToPower()){ //洗濯槽を開く washer.openLeftSide(); /汚れた衣服を装入する過程は省略/ //給水口を開く washer.openWaterHole(); //給水開始 washer.startWaterInjection(); /5 分待機/ //給水停止 washer.stopWaterInjection(); /洗剤を添加する過程は省略/ //洗濯開始 washer.startWashing(); /15 分後に停止/ washer.stopWashing();

     	/*
     	 * 脱水部分は省略
     	 * */
     }
    

    }

    /*

    • 以下は自動生成されたものを無視してください。。
    • */ @Override public boolean connectToPower() { // TODO Auto-generated method stub return false; }

    @Override public void openLeftSide() { // TODO Auto-generated method stub

    }

    @Override public void openWaterHole() { // TODO Auto-generated method stub

    }

    @Override public void startWaterInjection() { // TODO Auto-generated method stub

    }

    @Override public void stopWaterInjection() { // TODO Auto-generated method stub

    }

    @Override public void startWashing() { // TODO Auto-generated method stub

    }

    @Override public void stopWashing() { // TODO Auto-generated method stub

    }

    @Override public void openRightSide() { // TODO Auto-generated method stub

    }

    @Override public void startDewatering() { // TODO Auto-generated method stub

    }

    @Override public void stopDewatering() { // TODO Auto-generated method stub

    }

}

洗濯する過程を少し演示しただけで、これほど多くの操作を呼び出す必要がありました。しかも、この洗濯機の内部詳細を知っていなければ、そもそも使用できません。。洗濯には 60 分かかる可能性があります(給水 + 洗濯 + 脱水 + 排水)。その間、ほとんど何もできず、洗濯機のそばで絶えず機械を操作しながらうずくまる必要があります

リモコンが必要だと思います。ボタンが 2 つあります:

  • 洗濯
  • 脱水

すると、洗濯過程は以下のようになります:

  1. 洗濯ボタンを押すと、自動的に電源に接続し、自動的に洗濯槽を開き、自動的に 5 分間給水し、自動的に 15 分間洗濯します
  2. 脱水ボタンを押すと、自動的に脱水槽を開き、自動的に 10 分間脱水し、自動的に排水し、自動的に電源を切断します

これは素晴らしいです。昼食前に洗濯ボタンを 1 回押し、食べ終わったら衣服を右側に持っていき、脱水ボタンを 1 回押してから出勤します。���後に戻って衣服を干せばよいのです(もちろん、手動で衣服を左側から右側に持っていく過程は避けられませんが、それは本当に古いので、全自動洗濯機になることは期待できません。。)

自分で作ったリモコンを見てみましょう:

package FacadePattern;

/**

  • @author ayqy

  • リモコン(いわゆるファサード) */ public class WasherFacade { private Washer washer;

    public WasherFacade(Washer washer){ this.washer = washer; }

    /**

    • 自動洗濯 */ public void washing(){ //電源に接続 if(washer.connectToPower()){ //洗濯槽を開く washer.openLeftSide(); /汚れた衣服を装入する過程は省略/ //給水口を開く washer.openWaterHole(); //給水開始 washer.startWaterInjection(); /5 分待機/ //給水停止 washer.stopWaterInjection(); /洗剤を添加する過程は省略/ //洗濯開始 washer.startWashing(); /15 分後に停止/ washer.stopWashing(); } }

    /**

    • 自動脱水 */ public void dewashing(){ /電源に接続済みかどうかの判断過程は省略/ //右側の脱水槽を開く washer.openRightSide(); //右側の脱水槽の回転開始 washer.startDewatering(); //右側の脱水槽の回転停止 washer.stopDewatering();

      /*

      • 排水過程は省略
      • 電源遮断過程は省略
      • */ } }

リモコンがあれば、洗濯は以下のようになります:

package FacadePattern;

/**

  • @author ayqy

  • ファサードパターンを適用した半自動洗濯機のテスト(リモコンを利用) */ public class Test implements Washer{

    public static void main(String[] args) { //古い洗濯機を作成 Washer washer = new Test(); //ファサード(リモコン)を作成 WasherFacade facade = new WasherFacade(washer); //洗濯ボタンを押して洗濯開始 facade.washing(); /衣服をもう一方の側に持っていく/ //脱水ボタンを押して脱水開始 facade.dewashing(); }

    /*

    • 以下は自動生成されたものを無視してください。。
    • */ @Override public boolean connectToPower() { // TODO Auto-generated method stub return false; }

    @Override public void openLeftSide() { // TODO Auto-generated method stub

    }

    @Override public void openWaterHole() { // TODO Auto-generated method stub

    }

    @Override public void startWaterInjection() { // TODO Auto-generated method stub

    }

    @Override public void stopWaterInjection() { // TODO Auto-generated method stub

    }

    @Override public void startWashing() { // TODO Auto-generated method stub

    }

    @Override public void stopWashing() { // TODO Auto-generated method stub

    }

    @Override public void openRightSide() { // TODO Auto-generated method stub

    }

    @Override public void startDewatering() { // TODO Auto-generated method stub

    }

    @Override public void stopDewatering() { // TODO Auto-generated method stub

    }

}

本当に楽で気持ちいいですが、よく見ると、メソッド呼び出しをカプセル化するために 2 つのメソッドを定義しているだけです。何がすごいのでしょうか?新しいプロジェクトコード内で洗濯と脱水を担当する 2 つのメソッドを定義することと何が違うのでしょうか?もちろん違います。焦らないでください。

三.ファサードパターンの利点

  1. 低結合

    まず命名方法を見てみましょう。リモコンは WasherFacade という名前です。モジュールを分割する場合、Washer と一緒に配置するべきでしょう。その通りです。Facade を定義することで、Washer とコードの結合を成功させました。Washer に変更が発生した場合、冗長なプロジェクトコード内で 2 つのメソッドを探すのではなく、Facade を直接修正すればよいのです

  2. サブシステムのカプセル化を保護

    カプセル化された Washer を開いて修正したわけではありません。Washer のインターフェースを簡素化するためにいくつかのコードを追加しただけです。以前は呼び出し側が Washer の内部について詳しく知っていましたが、現在は Washer についてほとんど何も知りません(コンストラクタを除く)

  3. 複数の異なるオブジェクトを含むサブシステムに適している

    例の Washer は単一のオブジェクトに過ぎないので、このような単純なインターフェースは Washer 自体が提供するべきかもしれません。しかし、日常生活の半自動化を実現する場合、複数のオブジェクトを扱うことになります。例えば、ドア、窓、カーテン、テレビ、電子レンジ、洗濯機、パソコンなどです。ワンボタンで朝食の準備(自動点灯、電子レンジで自動加熱)、ワンボタンで午睡(自動でドアを閉め、自動でカーテンを閉め、自動で消灯)などの機能を実現したい場合、ファサードパターンが同様に適用できます:ファサードにいくつかの具体的なオブジェクトを持たせればよいだけです

  4. サブシステムのインターフェースを効果的に簡素化

    以前は洗濯する際に洗濯機のそばで絶えず操作する必要がありましたが、現在は「ワンボタンで完了」できます。これこそが求める简单易用なインターフェースです

  5. 「最少知識原則」を満たす

    「友達とだけ会話する」ことを実現しました。新しいシステムは Facade だけを知っており、それとだけ会話し、サブシステム内の多くの低レベルコンポーネントと会話するために走り回ることはありません

四.まとめ

ファサードパターンは、複雑なサブシステムに対してシンプルで使いやすい高レベルインターフェースを提供するために使用されます。

多くの低レベルコンポーネントに悩まされて解放されない場合、リモコンを作ってみてください。確かにそれが必要だと思います。。

コメント

コメントはまだありません

コメントを書く