君は心理学者なのか?

大学時代に心理学を専攻しなぜかプログラマになった、サイコ(心理学)プログラマかろてんの雑記。

劇的ビフォ◯アフターで学ぶデザインパターン〜facade pattern〜

f:id:karoten512:20180107002115j:plain

カレーを作るクラスを考える

玉ねぎきって、

じゃがいもをむいて切って、

カレールーをとかす。

そんな料理を実現するクラス群を作って考えてみます。

before

まずはfacade patternを使わずに書いてみます。

ソースコード

class Onion {
    cut() {
        console.log('玉ねぎが刻まれました');
    }
}
class Potato {
    peel() {
        console.log('じゃがいもの皮をむきました');
    }
    cut() {
        console.log('じゃがいものをきりました');        
    }
}
class CurryBase {
    dissolve() {
        console.log('ルーを溶かしました');
    }
}

class Main {
    static cookingStart() {

        /** 玉ねぎ2個を刻む */
        const onion1 = new Onion();
        onion1.cut();
        const onion2 = new Onion();
        onion2.cut();

        /** じゃがいも2個を剥いて切る */
        const potato1 = new Potato();
        potato1.peel();
        potato1.cut();
        const potato2 = new Potato();
        potato2.peel();
        potato2.cut();

        /** カレーのルーを溶かす */
        const curryBase = new CurryBase();
        curryBase.dissolve();
    }
}
Main.cookingStart();

クラス図

f:id:karoten512:20180107001136p:plain

これを見ると、

使う側のクラス(Mainクラス)が

使われる側のクラスを3つも知っていることになります。

使う側と使われる側の依存性が高いといえます。

この場合、使われる側のクラスのメソッド名などを修正した際、

使う側のクラスも修正しなくてはいけません。

after

今度はfacade patternを使って書いてみます。

ソースコード

class Onion {
    cut() {
        console.log('玉ねぎが刻まれました');
    }
}
class Potato {
    peel() {
        console.log('じゃがいもの皮をむきました');
    }
    cut() {
        console.log('じゃがいものをきりました');        
    }
}
class CurryBase {
    dissolve() {
        console.log('ルーを溶かしました');
    }
}

class Chef {
    cook() {
        
        /** 玉ねぎ2個を刻む */
        const onion1 = new Onion();
        onion1.cut();
        const onion2 = new Onion();
        onion2.cut();

        /** じゃがいも2個を剥いて切る */
        const potato1 = new Potato();
        potato1.peel();
        potato1.cut();
        const potato2 = new Potato();
        potato2.peel();
        potato2.cut();

        /** カレーのルーを溶かす */
        const curryBase = new CurryBase();
        curryBase.dissolve();        
    }
}

class Main {
    static cookingStart() {
        const chef = new Chef();
        chef.cook();
    }
}

Main.cookingStart();

クラス図

f:id:karoten512:20180107003841p:plain

なんということでしょう。

先ほどMainクラスは3つのクラスのことを知っている必要がありましたが、

今は1つ(Chefクラス)だけ知っていればOKとなりました。

匠(facade)のお陰で随分疎結合な設計となりました。

PotatoやCurryBase等のクラスのメソッド名などを修正しても、

使う側のクラス(Main)は修正する必要はありません。

すばらしいですね。

まとめ

facade patternは、

使う側と

使われる側を疎結合にする

デザインパターンでした。

そうすることにより、

クラス修正による影響を使う側がうけないので、

修正に対して強くなります。