はじめに

Java で Bridge パターンを実装をしてみました.

Bridge パターンとは

クライアントがアクセスするクラス (インタフェース) と実装クラスを分離して, それぞれを独立に変更できるようにする.

機能追加と機能実装の組み合わせ爆発を抑止することができる.

パターン適用前

言語と時間帯の分だけ, Man のサブクラスが増えていく.

なので, 言語や時間帯をひとつ追加すると その度にサブクラスが増えると言う問題がある.(組み合わせ爆発)

public class BridgeSample {
    public static void main (String args[]) {
        new JapaneseInTheMorning ().say ();
        new JapaneseInTheEvening ().say ();     
        new EnglishInTheMorning ().say ();
        new EnglishInTheEvening ().say ();      
    }
}

abstract class Man {
    public abstract void say ();
}

// ここで組み合わせ爆発が発生する!!!!
class JapaneseInTheMorning extends Man {
    public void say () { new Japanese ().inTheMorning (); }
}
class JapaneseInTheEvening extends Man {
    public void say () { new Japanese ().inTheEvening (); }
}
class EnglishInTheMorning extends Man {
    public void say () { new English ().inTheMorning (); }
}
class EnglishInTheEvening extends Man {
    public void say () { new English ().inTheEvening (); }
}

abstract class Language {
    public abstract void inTheMorning ();
    public abstract void inTheEvening ();   
}

class Japanese extends Language {
    public void inTheMorning () {
        System.out.println ("おはよう");
    }
    public void inTheEvening () {
        System.out.println ("こんばんわ");
    }
}

class English extends Language {
    public void inTheMorning () {
        System.out.println ("Good Morning");
    }
    public void inTheEvening () {
        System.out.println ("Good Evening");
    }
}

パターン適用後

言語と時間帯を分離して, 時間帯の引数で言語を渡す.

  • 言語の種類が増えても, 時間帯のクラスを増やす必要はない.
  • 時間帯の種類が増えても, 言語のクラスを増やす必要はない.

言語と時間帯はそれぞれ独立して機能拡張できる. つまり, 仕様変更に強い設計.

public class BridgeSample2 {
    public static void main (String args[]) {
        new Morning (new JapaneseSpeaker ()).say ();
        new Evening (new JapaneseSpeaker ()).say ();        
        new Morning (new EnglishSpeaker ()).say ();
        new Evening (new EnglishSpeaker ()).say ();     
    }
}

abstract class Man {
    protected Speaker speaker;
    public Man (Speaker speaker) {
        this.speaker = speaker;
    }
    public abstract void say ();

    protected void inTheMorning () {
        speaker.inTheMorning ();
    }
    protected void inTheEvening () {
        speaker.inTheEvening ();
    }
}

class Morning extends Man {
    public Morning (Speaker lang){ super (lang); }
    public void say () { inTheMorning (); }
}
class Evening extends Man {
    public Evening (Speaker lang){ super (lang); }  
    public void say () { inTheEvening (); }
}

abstract class Speaker {
    public abstract void inTheMorning ();
    public abstract void inTheEvening ();   
}

class JapaneseSpeaker extends Speaker {
    public void inTheMorning () {
        new Japanese ().inTheMorning ();
    }
    public void inTheEvening () {
        new Japanese ().inTheEvening ();        
    }
}

class EnglishSpeaker extends Speaker {
    public void inTheMorning () {
        new English ().inTheMorning ();
    }
    public void inTheEvening () {
        new English ().inTheEvening ();     
    }
}

abstract class Language {
    public abstract void inTheMorning ();
    public abstract void inTheEvening ();   
}

class Japanese extends Language {
    public void inTheMorning () {
        System.out.println ("おはよう");
    }
    public void inTheEvening () {
        System.out.println ("こんばんわ");
    }
}

class English extends Language {
    public void inTheMorning () {
        System.out.println ("Good Morning");
    }
    public void inTheEvening () {
        System.out.println ("Good Evening");
    }
}

実行結果