Design Pattern | Bridge Pattern(ブリッジパターン)

Bridgeパターンとは?

  • Bridgeという英単語はという意味である。
  • 現実世界の橋が川の両側をつなぐように、Bridgeパターンも2つの場所をつなぐ方式である。
  • 実装と抽象を分離する。機能クラス階層実装クラス階層の間に橋(Bridge)をかける役割を持つパターンである。
  • Bridgeパターンが交差する2つの場所は、機能クラス階層実装クラス階層である。
    • 機能クラスの階層: スーパークラスが基本的な機能を持ち、サブクラスで新しい機能を追加する場合の階層である。
    • 実装クラスの階層: スーパークラスが抽象メソッドによってインターフェースを規定し、サブクラスで具象メソッドによってそのインターフェースを実装する場合の階層である。
  • GoFのデザインパターンでは、構造に関するデザインパターンに分類される。

Bridgeパターンのサンプルプログラム

入力した文字列を指定回数およびランダム回数表示するサンプルプログラムである。

Class Diagram
Bridge Pattern

1. Displayクラス

機能クラス階層となる「表示」を行うクラスである。 このクラスが持つimplフィールドが、2つのクラス階層の「橋」になる。

Display.java

package com.devkuma.designpattern.structural.bridge;

public class Display {

    private DisplayImpl impl;

    public Display(DisplayImpl impl) {
        this.impl = impl;
    }

    public void open() {
        impl.rawOpen();
    }

    public void print() {
        impl.rawPrint();
    }

    public void close() {
        impl.rawClose();
    }

    public final void display() {
        open();
        print();
        close();
    }
}

2. CountDisplayクラス

機能クラス階層となる「指定回数表示」という機能を追加したクラスである。

CountDisplay.java

package com.devkuma.designpattern.structural.bridge;

public class CountDisplay extends Display {

    public CountDisplay(DisplayImpl impl) {
        super(impl);
    }

    public void multiDisplay(int times) {
        open();
        for (int i = 0; i < times; i++) {
            print();
        }
        close();
    }
}

3. RandomCountDisplayクラス

機能クラス階層となる「ランダム回数表示」という機能を追加したクラスである。

RandomCountDisplay.java

package com.devkuma.designpattern.structural.bridge;

import java.util.Random;

public class RandomCountDisplay extends CountDisplay {

    private Random random = new Random();

    public RandomCountDisplay(DisplayImpl impl) {
        super(impl);
    }

    public void randomDisplay(int times) {
        multiDisplay(random.nextInt(times));
    }
}

4. DisplayImplクラス

実装クラス階層となる「表示」用のメソッドを定義したクラスである。

DisplayImpl.java

public abstract class DisplayImpl {
    public abstract void rawOpen();
    public abstract void rawPrint();
    public abstract void rawClose();
}

5. StringDisplayImplクラス

実装クラス階層となる「文字列を使って表示」するクラスである。

StringDisplayImpl.java

package com.devkuma.designpattern.structural.bridge;

public class StringDisplayImpl extends DisplayImpl {

    private String string;
    private int width;

    public StringDisplayImpl(String string) {
        this.string = string;
        this.width = string.getBytes().length;
    }

    public void rawOpen() {
        printLine();
    }

    public void rawPrint() {
        System.out.println("|" + string + "|");
    }

    public void rawClose() {
        printLine();
    }

    private void printLine() {
        System.out.print("+");
        for (int i = 0; i < width; i++) {
            System.out.print("-");
        }
        System.out.println("+");
    }
}

6. Mainクラス

メイン処理を実行するクラスである。

Main.java

package com.devkuma.designpattern.structural.bridge;

public class Main {

    public static void main(String[] args) {
        Display display = new Display(new StringDisplayImpl("Display Test"));
        CountDisplay countDisplay = new CountDisplay(new StringDisplayImpl("CountDisplay Test"));
        RandomCountDisplay randomCountDisplay = new RandomCountDisplay(new StringDisplayImpl("RandomCountDisplay Test"));
        display.display();
        countDisplay.multiDisplay(5);
        randomCountDisplay.randomDisplay(10);
    }
}

7. 実行結果

+------------+
|Display Test|
+------------+
+-----------------+
|CountDisplay Test|
|CountDisplay Test|
|CountDisplay Test|
|CountDisplay Test|
|CountDisplay Test|
+-----------------+
+-----------------------+
|RandomCountDisplay Test|
|RandomCountDisplay Test|
|RandomCountDisplay Test|
|RandomCountDisplay Test|
|RandomCountDisplay Test|
|RandomCountDisplay Test|
+-----------------------+

メリット

前述のとおり、Bridgeパターンの特徴は機能クラスの階層実装クラスの階層を分けることである。この2つのクラス階層を分けておけば、それぞれのクラス階層を独立して拡張できる。
機能を追加するには、機能のクラス階層にクラスを追加する。このとき、実装クラス階層はまったく修正する必要がない。さらに、追加した機能はすべての実装で利用できるようになる。
サンプルプログラムでは、CountDisplayクラスやRandomCountDisplayクラスを追加することが機能追加に該当する。
このようにBridgeパターンでは、クラスの拡張を見通しよく行うことができる。