技術とか戦略とか

証券レガシーシステムを8年いじってから転職した普通の文系SEによるブログ。技術のみではなく趣味の戦略考察についても。

javaでのAbstract Factoryパターン

Abstract FactoryパターンはFactory Methodパターンを発展させたもので、生成するオブジェクトの組み合わせを間違えないために、1つのFactoryクラスに複数のオブジェクトの生成処理を実装するようにしたものです。
 
今回は、RPGのキャラクター作成を模したサンプルコードを作成してみました。
キャラクターの職業毎に、職業を示すオブジェクトとスキルを示すオブジェクトを生成します。
両オブジェクトの組み合わせ方を間違えないように、Abstract Factoryパターンにより組み合わせ方を限定しています。
 
【サンプルコード】
・AbstractJob.java
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
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
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
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
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
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クラスにまとめる
 */
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
/*
 * 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
/*
 * 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
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);
            }
        }
    }

}
 
【実行結果】
[プレイヤー:Player1]
・職業
 Warrior
・スキル
 QuickSlash
[プレイヤー:Player2]
・職業
 Magician
・スキル
 FireL1