クラスの継承関係 (extends) を大別すると以下の二つがあります。
それら継承関係を混在させて実装すると意図が不明瞭になってしまいます。そこでBridgeパターンでは二つの独立した継承関係を用意し、それぞれの継承関係のトップ同士を委譲によってつなぐ (Bridge) ことで継承を複数方向に行うことを可能にします。新たに継承が必要になったときには、どちらのツリーを拡張しようとしているのかを明確に意識できます。
sample.java
class Sample {
public static void main(String args[]) {
int val=1;
int arr[]={1};
// プロジェクトのある時点まではAdderが有する機能で満足していた
Adder intAdder = new Adder(new IntAdderImpl(val)); //abstractで要請された機能の実装方法を
Adder arrAdder = new Adder(new ArrAdderImpl(arr)); //切り換えるためにはこの引数を差し替える
intAdder.add(val);
intAdder.print();
arrAdder.add(arr);
arrAdder.print();
// 仕様変更か何かで機能が不足したため、Adderを継承したMultiAdderを用意し追加分を実装
MultiAdder intMultiAdder = new MultiAdder(new IntAdderImpl(val));
MultiAdder arrMultiAdder = new MultiAdder(new ArrAdderImpl(arr));
intMultiAdder.add(val);
intMultiAdder.multiAdd(val,8);
intMultiAdder.print();
arrMultiAdder.add(arr);
arrMultiAdder.multiAdd(arr,8);
arrMultiAdder.print();
// 参考: Adder型変数にMultiAdderを代入することは可能
Adder intAdder2 = new MultiAdder(new IntAdderImpl(val));
intAdder2.add(val);
// intAdder2.multiAdd(val,8); //ただしこれはエラー
intAdder2.print();
}
}
Adder.java
class Adder {
private AdderImpl impl;
public Adder(AdderImpl impl) {this.impl=impl;}
public void add(Object val) {impl.rawAdd(val);}
public void print() {impl.rawPrint();}
}
MultiAdder.java
class MultiAdder extends Adder {
public MultiAdder(AdderImpl impl) {super(impl);}
public void multiAdd(Object val, int times) {
for(int i=0; i<times; ++i) add(val);
}
}
AdderImpl.java
abstract class AdderImpl {
public abstract void rawAdd(Object val);
public abstract void rawPrint();
}
IntAdderImpl.java
class IntAdderImpl extends AdderImpl {
private int val;
public IntAdderImpl(int val) {this.val=val;}
public void rawAdd(Object val) {this.val += (Integer)val;}
public void rawPrint() {System.out.println(val);}
}
ArrAdderImpl.java
class ArrAdderImpl extends AdderImpl {
private int arr[];
public ArrAdderImpl(int arr[]) {
this.arr = new int[arr.length];
for(int i=0; i<arr.length; ++i) this.arr[i]=arr[i];
}
public void rawAdd(Object val) {
int tmp[] = arr; //参照をコピー
arr = new int[arr.length + ((int[])val).length]; //キャスト (型変換)
for(int i=0; i<tmp.length; ++i) arr[i]=tmp[i];
for(int i=0; i<((int[])val).length; ++i) arr[i+tmp.length]=((int[])val)[i];
}
public void rawPrint() {
for(int i=0; i<arr.length; ++i) System.out.print(arr[i] + " ");
System.out.println("");
}
}
$ javac Adder.java AdderImpl.java ArrAdderImpl.java IntAdderImpl.java MultiAdder.java sample.java && java Sample
2
1 1
10
1 1 1 1 1 1 1 1 1 1
2