🙄

デザインパターン ~FactoryMethodパターン~

2022/01/09に公開

FactoryMethodとは?

Template Methodパターンをインスタン生成を行う際に適用したデザインパターンのこと。

インスタンスの作り方をスーパークラス側で定めます(具体的なクラス名までは定めません)。
そして、具体的な肉付けはサブクラスで行います。

コードを書いてみよう

今回は、身分証明書カード(IDカード)を作る以下のプログラムを書いていきます。

パッケージ 名前 どんなクラスか
framework Product 抽象メソッドuseのみ定義されている抽象クラス
framework Factory メソッドcreateを実装している抽象クラス
idcard IDcard メソッドuseを実装しているクラス
idcard IDcardFactory メソッドcreateProduct, registerProductを実装しているクラス
無名 Main 動作テスト用のクラス

まずは、抽象クラス側として「製品」を表現するProductクラスを作成します。
ここで定めているのは、「何はともあれ、useできる(使用できる)もの」としています。
Product.java

package framework;

public abstract class Product {
  public abstract void use();
}

次に、抽象クラス側としてProductのインスタンスを生成し、製本の作成(createProduct)、製品の登録(registerProduct)を行うFactoryクラスを作成します

package framework;

public abstract class Factory {
  public final Product create(String owner) {
    Product p = createProduct(owner);
    registerProduct(p);
    return p;
  };
  protected abstract Product createProduct(String owner);
  protected abstract void registerProduct(Product product);
}

次に、具体クラス側として、認識番号カードを表すIDCardクラスを作成します。
このクラスは、抽象クラスProductのサブクラスとして定義します。

package idcard;
import framework.*;

public class IDCard extends Product {
  private String owner;
  IDCard(String owner) {
    System.out.println(owner + "のカードを作ります。");
    this.owner = owner;
  }
  public void use () {
    System.out.println(owner + "のカードを使います。");
  }
  public String getOwner() {
    return owner;
  }
}

次に、具体クラス側として、IDCardFactoryクラスを作成します。このクラスは、抽象クラスFactoryのサブクラスとして定義します。

package idcard;
import framework.*;
import java.util.*;

public class IDCardFactory extends Factory {
  private List owners = new ArrayList();
  protected Product createProduct(String owner) {
    return new IDCard(owner);
  }
  protected void registerProduct(Product product) {
    owners.add(((IDCard)product)).getOwner());
  }
  public List getOwners() {
    return owners;
  }
}

そして最後に動作確認用のMainクラスを作成します。

package idcard;
import framework.*;

public class Main {
  public static void main(String[] args) {
    Factory factory = new IDCardFactory();
    Product card1 = factory.create("Tom");
    Product card2 = factory.create("Andrew");
    Product card3 = factory.create("Ketty");
    card1.use();
    card2.use();
    card3.use();
  }
}

クラス図で見てみよう

このデザインパターンにはどんなメリットがあるのか?

複数人で開発するときの意思疎通がしやすくなる

frameworkパッケージに定義されているスーパークラス側で、インスタンス生成の作り方について骨組みを決められるので、複数人で開発するときの意思疎通がしやすくなります。

継承先のパッケージに依存しない

frameworkパッケージに定義されているスーパークラス側では、それを継承して具体的に何のクラスが作られるかは知らないので、今回で言えばidcardパッケージに依存しない状態になります。
そうすることで、idcard以外のクラスを作成したい場合でも、パッケージ側には修正が不要になります。

Discussion