Bridgeパターンは、機能のクラス階層と実装のクラス階層を橋渡しするパターンです。
機能のクラス階層と実装のクラス階層を分けることで、実装毎に機能を書かなくて良くなりますし、その逆に機能毎に実装を書かなくて良くなります。
結果として、重複した記述を減らすことができ、保守性を向上させることができます。
今回は、RPGのダメージ計算を模したサンプルコードを作成してみました。
機能のクラス階層ではダメージの与え方を定義し、実装のクラス階層では具体的なダメージ計算式を定義しています。
Bridgeパターンの適用により、ダメージの与え方毎にダメージ計算式を書かなくて良くなっている点、逆にダメージ計算式毎にダメージの与え方を書かなくて良くなっている点に注目です。
【サンプルコード】
・DamageCalc.java
// ダメージ計算機能
public class DamageCalc {
protected DamageCalcImpl damageCalcImpl;
protected int damage = 0;
public DamageCalc (DamageCalcImpl damageCalcImpl) {
this.damageCalcImpl = damageCalcImpl;
}
protected void clearDamage() {
damage = 0;
}
public int getDamage() {
return this.damage;
}
public void damageCalc(int offenceValue, int defenceValue) {
clearDamage();
damage = damageCalcImpl.damageCalc(offenceValue,defenceValue);
}
}
・MultipleDamageCalc.java
// ダメージ計算機能(連続攻撃に対応するための拡張)
public class MultipleDamageCalc extends DamageCalc {
public MultipleDamageCalc(DamageCalcImpl damageCalcImpl) {
super(damageCalcImpl);
}
public void multipleDamageCalc
(int offenceValue, int defenceValue, int damageTimes) {
clearDamage();
for(int i = 0;i < damageTimes;i++) {
damage += damageCalcImpl.damageCalc(offenceValue,defenceValue);
}
}
}
・DamageCalcImpl.java
// ダメージ計算の実装(抽象クラス)
public abstract class DamageCalcImpl {
public abstract int damageCalc(int offenceValue, int defenceValue);
}
・NormalDamageCalcImpl.java
// ダメージ計算の実装(通常のダメージ計算)
public class NormalDamageCalcImpl extends DamageCalcImpl {
public int damageCalc(int offenceValue, int defenceValue) {
int damage = 0;
damage = offenceValue - (defenceValue/2);
if (damage < 0) {
damage = 0;
}
return damage;
}
}
・IgnoreDefenceDamageCalcImpl.java
// ダメージ計算の実装(防御無視のダメージ計算)
public class IgnoreDefenceDamageCalcImpl extends DamageCalcImpl {
public int damageCalc(int offenceValue, int defenceValue) {
int damage = 0;
damage = offenceValue;
if (damage < 0) {
damage = 0;
}
return damage;
}
}
・DamageCalcMain.java
// ダメージ計算のメインクラス
public class DamageCalcMain {
public static void main(String[] args){
int offenceValue = 100;
int defenceValue = 50;
int multipleDamageTimes = 4; // 連続攻撃の場合のみ使用
NormalDamageCalcImpl normalDamageCalcImpl =
new NormalDamageCalcImpl();
IgnoreDefenceDamageCalcImpl ignoreDefenceDamageCalcImpl =
new IgnoreDefenceDamageCalcImpl();
System.out.println("■通常のダメージ計算(1回攻撃)");
DamageCalc damageCalc1 = new DamageCalc(normalDamageCalcImpl);
damageCalc1.damageCalc(offenceValue, defenceValue);
System.out.println(" ダメージ:" + damageCalc1.getDamage());
// 実装を独立させることで、実装毎に機能を書かなくて良い
// (通常の1回攻撃メソッドと
// 防御無視の1回攻撃メソッドを用意しなくて良い)
System.out.println("■防御無視のダメージ計算(1回攻撃)");
DamageCalc damageCalc2 =
new DamageCalc(ignoreDefenceDamageCalcImpl);
damageCalc2.damageCalc(offenceValue, defenceValue);
System.out.println(" ダメージ:" + damageCalc2.getDamage());
// 機能を独立させることで、機能毎に実装を書かなくて良い
// (1回攻撃の防御無視メソッドと
// 複数攻撃の防御無視メソッドを用意しなくて良い)
System.out.println("■防御無視のダメージ計算(4回攻撃)");
MultipleDamageCalc multipleDamageCalc1 =
new MultipleDamageCalc(ignoreDefenceDamageCalcImpl);
multipleDamageCalc1.multipleDamageCalc
(offenceValue, defenceValue, multipleDamageTimes);
System.out.println(" ダメージ:" + multipleDamageCalc1.getDamage());
}
}
【実行結果】
■通常のダメージ計算(1回攻撃)
ダメージ:75
■防御無視のダメージ計算(1回攻撃)
ダメージ:100
■防御無視のダメージ計算(4回攻撃)
ダメージ:400