Facadeクラスとは、使い方が複雑になっているクラス群をまとめ、使いやすい形のインターフェースとして外部に提供するクラスのことを指します。
デザインパターンでは、このFacadeクラスを利用するパターンをFacadeパターンと呼びます。
(ちなみに、Facadeは「窓口」を意味する単語です)
サンプルコードとして、RPGのダメージ計算を模したプログラムを作成してみました。
RPGのダメージ計算は複雑で、そのRPGに詳しくない人が正しく計算式を実装するのは困難なのですが、Facadeクラスを用いることにより、Facadeクラスの利用者は詳しい知識を持たずとも正しく計算式を実装することが可能となります。
【サンプルコード】
・PhysicsBaseDamageCalc.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public final class PhysicsBaseDamageCalc { private int baseDamage = 0; public PhysicsBaseDamageCalc(int physicsPower) { baseDamage = physicsPower / 2; //攻撃力の半分がダメージ } public int getBaseDamage() { return baseDamage; } } |
・MagicBaseDamageCalc.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public final class MagicBaseDamageCalc { private int baseDamage = 0; public MagicBaseDamageCalc(int magicID) { if (magicID == 0) { //魔法「FireL1」 baseDamage = 15; } else if (magicID == 1) { //魔法「FireL2」 baseDamage = 60; } else if (magicID == 2) { //魔法「FireL3」 baseDamage = 120; } else { //例外処理 System.out.println("指定された魔法IDは未実装です"); System.exit(1); } } public int getBaseDamage() { return baseDamage; } } |
・DamageRandomize.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import java.util.Random; public final class DamageRandomize { private int damage = 0; public DamageRandomize(int baseDamage) { // 7/8、8/8、9/8の何れかの値をかけてランダム化 damage = baseDamage * (new Random().nextInt(3) + 7) / 8; } public int getDamage() { return damage; } } |
・DamageCalcFacade.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public final class DamageCalcFacade { private int damage = 0; public DamageCalcFacade (int physicsPower,int magicID) { int baseDamage = 0; if (physicsPower >= 0 || magicID == -1) { //物理攻撃 baseDamage = new PhysicsBaseDamageCalc(physicsPower) .getBaseDamage(); } else if (physicsPower == -1 || magicID >= 0) { //魔法攻撃 baseDamage = new MagicBaseDamageCalc(magicID) .getBaseDamage(); } else { //例外処理 System.out.println("不正なダメージ計算です"); System.exit(1); } damage = new DamageRandomize(baseDamage).getDamage(); } public int getDamage() { return damage; } } |
・DamageCalcMain.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
public class DamageCalcMain { public static void main(String[] args){ int physicsPower = -1; int magicID = -1; int damage = 0; // 引数から物理攻撃力、魔法IDを取得 if (args.length == 2) { physicsPower = Integer.parseInt(args[0]); magicID = Integer.parseInt(args[1]); } // ダメージ計算→計算式を知らないとこのように実装できない /* int baseDamage = 0; if (physicsPower >= 0 || magicID == -1) { //物理攻撃 baseDamage = new PhysicsBaseDamageCalc(physicsPower) .getBaseDamage(); } else if (physicsPower == -1 || magicID >= 0) { //魔法攻撃 baseDamage = new MagicBaseDamageCalc(magicID) .getBaseDamage(); } else { //例外処理 System.out.println("不正なダメージ計算です"); System.exit(1); } damage = new DamageRandomize(baseDamage).getDamage(); */ // 利用者側で複雑な計算式を考えたくないので、Facadeクラスに任せる damage = new DamageCalcFacade(physicsPower,magicID).getDamage(); System.out.println("ダメージは"+damage); System.exit(0); } } |
【実行結果】
1 |
ダメージは52 |
※第1引数に-1、第2引数に1を指定した場合
いかがでしたでしょうか。
デザインパターンはオブジェクト指向プログラミングのプログラミング手法をまとめたものなのですが、このFacadeパターンは手続き型言語にも応用が可能です。
複雑な処理を共通クラス・共通関数・共通スクリプト等のような形で切り出して利用者側に意識させないようにする、というのは現場でも良く使う手法なので、覚えておいて損はありません。
では、また次回!
コメント