はじめに

Gof のデザインパターンで Adapter, Facade, Proxy があり, 違いがわからなかったので, 整理してみた.

まずは定義から

Adapter

インタフェースを変換することにより, インタフェースに互換性がない クラス同士を接続する.

既存のクラスに対して修正を加えることなく, インタフェースを変更することができる.

継承を利用する場合と委譲を利用する場合がある.

Facade

複数のクラス群からなるサブシステムにアクセスするための, インタフェースを提供する.

異なるサブシステムを単純な操作だけを持った Facade クラスで結び, サブシステム間の独立性を高める事を目的とする.

facade とは, 正面という意味.

Proxy

オブジェクトへのアクセスをフックするための代理オブジェクトを提供する.

Proxy は英語で代理人.

ラッパー

ラッパーという概念がある.

あるクラスや関数, データ型などが提供する機能やデータを含み, 別の形で提供するもののこと.

どれもラッパーと言える.

オブジェクト思考のこころより

オブジェクト思考のこころという本に, Adapter と Facade の比較表がある.

以下, Proxy パターンも交えて整理すると,

  • Facade はインタフェースを簡素化する

  • Adapter は既存インタフェースを他のインタフェースに変換する

  • Proxy はインタフェースを変更せずに機能追加する.

                                                    Facade   Adapter   Proxy
    

既存クラスがある? ○ ○ ○ インタフェースを再設計する? × ○ × ボリモーフィズムによるオブジェクトの振る舞いが必要? × ○ × より簡素なインタフェースが必要? ○ × ×

コードでの例

class Target {
    void printInt (int i) {
        System.out.println (i);
    }

    void printLong (long l) {
        System.out.println (l);
    }
}

class Adapter {
    Target target;
    Adapter (Target target) {
        this.target = target;
    }

    void printInt (Integer i) {
        target.printInt (i);
    }

    void printLong (Long l) {
        target.printLong (l);
    }

}

class Facade {
    Target target;
    Facade (Target target) {
        this.target = target;
    }

    void print (long l) {
        target.printLong (l);
    }
}

class Proxy {
    Target target;
    int intCount = 0;
    int intCache= 0;
    long longCount = 0;
    long longCache = 0; 

    Proxy (Target target) {
        this.target = target;
    }

    void printInt (Integer i) {
        target.printInt (i);
        intCount++;
        intCache = i;
    }

    void printLong (Long l) {
        target.printLong (l);
        longCount++;
        longCache = l;
    }
}