Factory Methodってどんなパターン?
複数に分割したクラスのインスタンスを生成する際は、それぞれコンストラクタを呼んで生成するのではなく、「片方のインスタンスは生成するが、もう片方のインスタンスは既に作成済みの片方のインスタンスに頼んで生成してもらうという」というのが基本方針になります。
通常、もう片方のクラス内でインスタンスを作ってくれるメソッドを「ファクトリメソッド」と呼びます。
どんなメリットがあるの?
クラスを複数のクラスに分割した場合は、それぞれ適切なペアのインスタンスを生成しなければならないということが、クラスによってはあたっりするものですよね。
特に、複雑度が高く、サブクラスの数が多いシステムの場合は、それが起こる可能性が高まります。
その際に、複雑なシステムになればなるほどどのペアでインスタンスを生成したらよいか、わからなくなりがちになりますが、このパターンを使うことで開発時にその迷いがなくなります。
前提条件
「Factory Methodパターン」を使うための前提条件としては、下記2つを満たしていることになります。
- 1つのまとまった機能を1つのクラスで作るのではなく、2つ以上のクラスに分解して作った場合
- その分割したクラスを、それぞれ継承させてサブクラスとして使う場合。
どんな時に使うと効果的なのか?
上記、二つを満たせばFactory Methodパターンを使うことはできますが、特に効果を発揮するのは、下記2つの条件を満たしたクラスを作る場合です。
- 継承させたサブクラスが、今後数が増えると想定される場合
- (一番大事)サブクラス同士をペアで使うことが、明確である場合
特に重要なのが、二つ目です。サブクラス同士がペアで使うことが明確でなければ、開発者がイマイチ理解できず、せっかく作ったクラスが台無しになってしまいます。
実際に使ってみましょう。
イメージ図
会社に訪問者が来て、その訪問者に応じて、応対する担当部署を振り分けるクラスを例に実装してみましょう。
クラス図のイメージ
クラス図にすると下記のような感じです。(小さくて見難い場合は、お手数ですが拡大してご覧下さい。)
前提条件で書いたようにしています。
- 二つの親クラスを作っている。(「訪問抽象クラス」、「部署抽象クラス」)
- それぞれサブクラスを持っている。
実装する。
AbstractDepartment.java
1 2 3 4 5 6 7 8 9 10 11 |
package factoryMethodSample; /** * 部署抽象クラス */ public abstract class AbstractDepartment { /* 接待する抽象メソッド */ abstract void reception(); } |
AbstractVisit.java
1 2 3 4 5 6 7 8 9 10 |
package factoryMethodSample; /** * 訪問抽象クラス */ public abstract class AbstractVisit { public abstract AbstractDepartment call(); } |
EigyoDepartment.java
1 2 3 4 5 6 7 8 9 |
package factoryMethodSample; public class EigyoDepartment extends AbstractDepartment { public void reception() { System.out.println("ようこそ、いらっしゃいましたわが社へ。"); } } |
JinjiDepartment.java
1 2 3 4 5 6 7 8 9 |
package factoryMethodSample; public class JinjiDepartment extends AbstractDepartment { public void reception() { System.out.println("内定おめでとうございます。今日は何でも質問してくださいね。"); } } |
Madoguti.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package factoryMethodSample; /** * 受付窓口クラス */ public class Madoguti { public static void main(String[] args) { //訪問者が取引先だった場合 AbstractVisit adp = new TorihikisakiVisit(); AbstractDepartment adt = adp.call(); adt.reception(); //訪問者が内定者だった場合 AbstractVisit adp2 = new NaiteishaVisit(); AbstractDepartment adt2 = adp2.call(); adt2.reception(); } } |
NaiteishaVisit.java
1 2 3 4 5 6 7 8 9 |
package factoryMethodSample; public class NaiteishaVisit extends AbstractVisit{ public JinjiDepartment call() { return new JinjiDepartment(); } } |
TorihikisakiVisit.java
1 2 3 4 5 6 7 8 9 |
package factoryMethodSample; public class TorihikisakiVisit extends AbstractVisit { public EigyoDepartment call() { return new EigyoDepartment(); } } |
実行結果
Factory Methodのポイント
呼び出す元となるプログラムでは、スーパークラスのオブジェクト名に代入しています。
//訪問者が取引先だった場合
AbstractVisit(スーパークラス) adp = new TorihikisakiVisit()(子クラス);
これは、「オブジェクト指向」の基本でもある「ポリフォルリズム:多様性」ですね。
多様性のメリットとしては、「子クラスの数を増やしても、あいまいなものと捉えて、ソースコードの重複を減らせる」ということでした。
なお、多様性については、下記の記事でも解説していますので、参考になさってください。
それに加えて、「Factory Method」のデザインパターンを使うと、「サブクラス間にペアがある場合は、適切なペアのクラスをインスタンス化できる」というメリットを体感いただきました。
今回の例で言えば、「取引先が着たら、営業部をインスタンス化する」、「内定者が着たら、人事部をインスタンス化する」というようにですね。
この記事へのコメントはありません。