Abstract FactoryパターンはFactory Methodパターンを発展させたもので、生成するオブジェクトの組み合わせを間違えないために、1つのFactoryクラスに複数のオブジェクトの生成処理を実装するようにしたものです。
今回は、RPGのキャラクター作成を模したサンプルコードを作成してみました。
キャラクターの職業毎に、職業を示すオブジェクトとスキルを示すオブジェクトを生成します。
両オブジェクトの組み合わせ方を間違えないように、Abstract Factoryパターンにより組み合わせ方を限定しています。
【サンプルコード】
・AbstractJob.java
1 2 3 4 5 6 7 8 9 10 11 |
public abstract class AbstractJob { protected String playerName; protected String jobName; public abstract void setPlayerName(String playerName); public abstract String getPlayerName(); public abstract void setJobName(String jobName); public abstract String getJobName(); } |
・WarriorJob.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class WarriorJob extends AbstractJob { public void setPlayerName(String playerName) { this.playerName = playerName; } public String getPlayerName() { return this.playerName; } public void setJobName(String jobName) { this.jobName = jobName; } public String getJobName() { return this.jobName; } } |
・MagicianJob.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class MagicianJob extends AbstractJob { public void setPlayerName(String playerName) { this.playerName = playerName; } public String getPlayerName() { return this.playerName; } public void setJobName(String jobName) { this.jobName = jobName; } public String getJobName() { return this.jobName; } } |
・AbstractSkill.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.ArrayList; import java.util.List; public abstract class AbstractSkill { protected String playerName; protected List<String> skillList = new ArrayList<String>(); public abstract void setPlayerName(String playerName); public abstract String getPlayerName(); public abstract void setSkill(String skill); public abstract List<String> getSkill(); } |
・WarriorSkill.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import java.util.List; public class WarriorSkill extends AbstractSkill { public void setPlayerName(String playerName) { this.playerName = playerName; } public String getPlayerName() { return this.playerName; } public void setSkill(String skill) { this.skillList.add(skill); } public List<String> getSkill() { return this.skillList; } } |
・MagicianSkill.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import java.util.List; public class MagicianSkill extends AbstractSkill { public void setPlayerName(String playerName) { this.playerName = playerName; } public String getPlayerName() { return this.playerName; } public void setSkill(String skill) { this.skillList.add(skill); } public List<String> getSkill() { return this.skillList; } } |
・AbstractJobFactory.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/* * 生成するオブジェクトの組み合わせを間違えないように、 * 複数のオブジェクトの生成を1クラスにまとめる */ public abstract class AbstractFactory { public final AbstractJob createJob(String playerName) { AbstractJob abstractJob = createJobLogic(playerName); return abstractJob; } protected abstract AbstractJob createJobLogic(String playerName); public final AbstractSkill createSkill(String playerName) { AbstractSkill abstractSkill = createSkillLogic(playerName); return abstractSkill; } protected abstract AbstractSkill createSkillLogic(String playerName); } |
・WarriorFactory.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/* * WarriorJobとWarriorSkillの組み合わせ */ public class WarriorFactory extends AbstractFactory { protected AbstractJob createJobLogic(String playerName) { WarriorJob warriorJob = new WarriorJob(); warriorJob.setPlayerName(playerName); warriorJob.setJobName("Warrior"); return warriorJob; } protected AbstractSkill createSkillLogic(String playerName) { WarriorSkill warriorSkill = new WarriorSkill(); warriorSkill.setPlayerName(playerName); warriorSkill.setSkill("QuickSlash"); return warriorSkill; } } |
・MagicianFactory.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/* * MagicianJobとMagicianSkillの組み合わせ */ public class MagicianFactory extends AbstractFactory { protected AbstractJob createJobLogic(String playerName) { MagicianJob magicianJob = new MagicianJob(); magicianJob.setPlayerName(playerName); magicianJob.setJobName("Magician"); return magicianJob; } protected AbstractSkill createSkillLogic(String playerName) { MagicianSkill magicianSkill = new MagicianSkill(); magicianSkill.setPlayerName(playerName); magicianSkill.setSkill("FireL1"); return magicianSkill; } } |
・CreateJobMain.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 38 |
import java.util.Iterator; public class CreateJobMain { public static void main(String[] args){ // Factoryメソッドの定義 WarriorFactory warriorFactory = new WarriorFactory(); MagicianFactory magicianFactory = new MagicianFactory(); // Factoryメソッドによりオブジェクトを生成 AbstractJob player1Job = warriorFactory.createJob("Player1"); AbstractSkill player1Skill = warriorFactory.createSkill("Player1"); AbstractJob player2Job = magicianFactory.createJob("Player2"); AbstractSkill player2Skill = magicianFactory.createSkill("Player1"); // 生成されたオブジェクトの内容を確認 displayJob(player1Job,player1Skill); displayJob(player2Job,player2Skill); } private static void displayJob(AbstractJob job,AbstractSkill skill) { System.out.println("[プレイヤー:"+job.getPlayerName()+"]"); System.out.println("・職業"); System.out.println(" "+job.getJobName()); System.out.println("・スキル"); Iterator<String> iterator = skill.getSkill().iterator(); if (!iterator.hasNext()) { System.out.println(" None"); } else { while (iterator.hasNext()) { String str = iterator.next(); System.out.println(" "+str); } } } } |
【実行結果】
1 2 3 4 5 6 7 8 9 10 |
[プレイヤー:Player1] ・職業 Warrior ・スキル QuickSlash [プレイヤー:Player2] ・職業 Magician ・スキル FireL1 |
いかがでしたでしょうか?
デザインパターンの勉強をしていて、個人的に一番わかりにくいと思ったのは今回紹介したAbstract Factoryパターンです。
このデザインパターンは「複数のオブジェクトを組み合わせる場合に、その組み合わせ方を間違えないようにする」という意図を持ったデザインパターンなのですが、「Abstract Factory(抽象的な工場)」という名前からこの意図を読み取るのは難しいと思いますし、クラス図やサンプルコードを眺めても複雑で意図を理解するのは難しいと思います。
今回の記事で、その意図が伝われば幸いです。
まだ紹介していないデザインパターンもありますので、これからも少しずつ紹介していきたいと思います!
コメント