Bridge パターン (あるクラスにおける機能拡張と実装を分離し, それらを独立して管理する)

[Bridge] という英単語は, [橋] を意味する.

このパターンは, 以下で説明している [1, 2] の架け橋を提供するパターン.

まず, 継承の目的について考えてみる. 継承の目的としては, 主に次の2つが考えられる:

1. [機能追加] (スーパークラスが持っていない機能をサブクラスで追加) を目的
としたもの
2. [機能実装] (スーパークラスで定義したインタフェースをサブクラスで実装) を
目的としたもの

次は, この [1, 2] の継承関係が発達していくと, どういう問題が発生するかについて説明したいと思う.

下図を見てください.

抽象クラス A と, A を継承し抽象メソッドを実装したクラス A1, A2 の下図の関係があるとする.

_images/designpattern-bridge015.gif

上図状態のクラス関係に, 抽象クラス A への機能追加のため, クラス AB を追加したとする. (下図参照)

この場合, クラス AB からは, クラス A1, A2 の実装メソッドをそのまま使用することができない. (A を継承しているので, 抽象メソッドのインタフェースは存在するが, クラス AB の実装がない)

_images/designpattern-bridge024.gif

そこで, 下図のように A1, A2 と同じ実装内容のクラス A1’, A2’ を, クラス AB のサブクラスとして追加した. これでひとまずクラス AB からも, クラス A1’, A2’ の実装メソッドを使用できるようになった.

が, またまた今度は, クラス AB に機能を追加しなくてはいけなくなったので, クラス ABC を追加した. そのため, クラス A1’‘, A2’’ を追加した.

_images/designpattern-bridge034.gif

このように, クラス A (AB) に機能を追加しようと思う, そのサブクラス (機能実装) まで追加しなければならない. つまり, 機能を追加する度に, その実装クラス (A1, A2) まで追加していかなければならなくなる. (機能追加クラス (1.の継承関係) 数 x 実装クラス (2.の継承関係) 数分のクラスを作成しなければならなくなる)

この問題を解消してくれるのが [Bridge] パターンである.

下図をみてください.

_images/designpattern-bridge044.gif

このように機能実装関係のクラスを, クラス A に保持させる (架け橋を作る) ことにより, 機能追加しても実装関係のクラス階層には影響せず, また逆に, 実装クラスを追加しても機能のクラス階層に影響しない構造にすることができた.

役割

  1. Abstraction (抽象化):
機能追加の継承関係の最上位クラス. [Implementor] を内部に保持し, [Implementor] のメソッドを使用した基本的な機能を提供する.
  1. RefinedAbstraction (改善した抽象化):
[Abstraction] を機能追加したクラス. [Abstraction] とは, 機能追加の継承関係にある.
  1. Implementor (実装者):
機能実装の継承関係の最上位クラス. [Abstraction] が使用するメソッドのインタフェースを定義する.
  1. ConcreteImplementor (具体的な実装者):
[Implementor] が定めたインタフェースを実装する.
  1. Client (利用者):
[Bridge] パターンを適用したクラスを利用し処理する.

クラス図

Bridge パターンのクラス図

_images/designpattern-bridge052.gif

ソースコード

  1. Abstraction.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class Abstraction{
    // 機能実装クラス (Implementor) のインスタンスを保持している
    private Implementor impl;

    public Abstraction(Implementor impl){
	this.impl = impl;
    }

    public void abstractionMethod(){
	impl.implMethod();
    }
}
  1. RefinedAbstraction.java
1
2
3
4
5
6
7
8
9
public class RefinedAbstraction extends Abstraction{
    public RefinedAbstraction(Implementor impl){
	super(impl);
    }

    public void refinedMethod(){
	System.out.println("追加機能");
    }
}
  1. Implementor.java
1
2
3
public abstract class Implementor{
    public abstract void implMethod();
}
  1. ConcreteImplementor.java
1
2
3
4
5
public class ConcreteImplementor extends Implementor{
    public void implMethod(){
	System.out.println("実装機能");
    }
}
  1. Client.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class Client{
    public static void main(String[] args){
	Abstraction abstraction = new Abstraction(new ConcreteImplementor());
	RefinedAbstraction refinedAbstraction = new RefinedAbstraction(new ConcreteImplementor());

	abstraction.abstractionMethod();
	refinedAbstraction.abstractionMethod();
	refinedAbstraction.refinedMethod();
    }
}

上記のプログラムの実行結果:

[wtopia Bridge]$ java Client
実装機能
実装機能
追加機能