
Abstract Factoryってどんなパターン?
組み合わせて使う多数のサブクラス群を、まとめて交換できるようにするパターンです。
メリット?
実行するメインプログラムを修正することなく、サブクラス群を環境変化に伴って交換することができることです。
典型的な利用例
- OSによって、一部のクラスの作りを変更したい場合
- SQL文を、DBMSのパッケージによって変更したい場合
どのようなクラス構成になるのか?
「環境のスーパークラス」を作っておき、OSやDBMSによって、異なる別々のサブクラスを作ります。
サブクラスのオブジェクト生成を専門に行うクラス(ファクトリクラス)を作り、そのクラス内で、ペアの関連するクラスをまとめてnewします。
Factory Methodとの違いは?
Factory Methodパターンと、構造や概念が少し似ていますよね。
ただ、Factory Methodと異なり、片方のクラスにもう片方のクラスのnewを任せるのではなく、newする専門のクラスが、関連するサブクラスのnewをまとめて実施するという点です。
また、Factory Methodでは、基本的に2つのサブクラスのペアでしたが、3つでも4つでも、サブクラスの関連を拡張しやすいという点も特徴です。
参考までに、「Factory Method」については、下記の記事で解説しています。
どのように使うのか?
利用したいメインプログラム側では、そのファクトリクラスを呼びます。
明示的に特定のクラスをnewしていないので、後で別のファクトリクラスのクラスに置き換えるだけで、サブクラス群もまるまる交換することが可能になります。
実際に実装してみる。
まずは、イメージとして、「Factory Method」パターンでも使った下記の例を「AbstractFactory」パターンにも当てはめてみます。
完成後のクラスのイメージはこんな感じです。
Main.java(クラスを利用するプログラム)
「AbstractFactory」で使用するメインプログラムです。このプログラムではクラスをnewしないので、別のクラスに差し替えた場合でも、このクラスを修正する必要がなくなります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package AbstractFactory; public class Main { public static void main(String args[]) { MadogutiFactory madogutifact = MadogutiFactory.getFactory("取引先の社長"); System.out.println("取引先の社長がいらっしゃいました。"+ madogutifact.createDepartment().getName() + "の" + madogutifact.createTantosha().getName() +"さん、対応お願い致します。" ); MadogutiFactory madogutifact2 = MadogutiFactory.getFactory("内定者"); System.out.println("内定者の方がいらっしゃいました。"+ madogutifact2.createDepartment().getName() + "の" + madogutifact2.createTantosha().getName() +"さん、対応お願い致します。" ); } } |
MadogutiFactory.java(サブクラス群をまとめて作る専用のクラスの親)
これを、Mainメソッドから呼びます。どちらのサブクラス群をnewするかは、引数でもらう変数で分岐させています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package AbstractFactory; /** * ファクトリの抽象クラスです。 */ public abstract class MadogutiFactory { abstract Department createDepartment(); abstract Tanto createTantosha(); public static MadogutiFactory getFactory(String Visitor) { if(Visitor.equals("取引先の社長")) { return new EigyoFactory(); }else if(Visitor.equals("内定者")) { return new JinjiFactory(); }else { return null; } } } |
EigyoFactory.java(サブクラス群をまとめて作る専用のクラスの子1)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package AbstractFactory; public class EigyoFactory extends MadogutiFactory { Department createDepartment(){ return new EigyoDepartment(); } Tanto createTantosha(){ return new EigyoTanto(); } } |
JinjiFactory.java(サブクラス群をまとめて作る専用のクラスの子2)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package AbstractFactory; public class JinjiFactory extends MadogutiFactory { Department createDepartment(){ return new JinjiDepartment(); } Tanto createTantosha(){ return new JinjiTanto(); } } |
Department.java(サブクラス1の親)
1 2 3 4 5 6 |
package AbstractFactory; public abstract class Department { abstract String getName(); } |
EigyoDepartment.java(サブクラス1の子1)
1 2 3 4 5 6 7 8 9 |
package AbstractFactory; public class EigyoDepartment extends Department{ public String getName(){ return "営業部"; } } |
JinjiDepartmentjava(サブクラス1の子2)
1 2 3 4 5 6 7 8 9 |
package AbstractFactory; public class JinjiDepartment extends Department{ public String getName() { return "人事部"; } } |
Tanto.java(サブクラス2の親)
1 2 3 4 5 6 7 |
package AbstractFactory; public abstract class Tanto { abstract String getName(); } |
EigyoTanto.java(サブクラス2の子1)
1 2 3 4 5 6 7 8 9 |
package AbstractFactory; public class EigyoTanto extends Tanto { public String getName() { return "鈴木高弘"; } } |
JinjiTanto.java(サブクラス2の子2)
1 2 3 4 5 6 7 8 9 |
package AbstractFactory; public class JinjiTanto extends Tanto { public String getName() { return "小泉舞"; } } |
実行結果
Abstract Factoryを使う上での注意点
Factory Methodと同様にあくまで、呼ぶサブクラスのペアが決まっている場合でのみしか効果を発揮しません。
複雑な条件で、呼ぶサブクラスが変わってくるようなシステムの場合は、あまり有効な手法ではないでしょう。
その場合は、メインプログラムで直接newした方がよいと思います。
この記事へのコメントはありません。