デザインパターン ~Factory Method~


1. はじめに

GoFのデザインパターンにおける、Factory Methodパターンについてまとめます。

2. Factory Methodパターンとは

  • Factoryという英単語は、工場という意味になります。
  • Factory Methodパターンは、インスタンスの作り方をスーパークラスで定め、具体的な生成処理はサブクラス側で行う方式です。
  • インスタンスを生成する工場をTmplate Methodパターンで構成したものがFactory Methodパターンになります。
  • GoFのデザインパターンでは、生成に関するデザインパターンに分類されます。

3. サンプルクラス図

4. サンプルプログラム

IDカード工場から、IDカードを作成するプログラムです。

4-1. Factoryクラス

Factoryの基底となるクラスです。インスタンスの作り方を定めます。

Factory.java
package framework;

public abstract class Factory {

    public final Product create(String owner) {
        Product product = createProduct(owner);
        registerProduct(product);
        return product;
    }

    protected abstract Product createProduct(String owner);
    protected abstract void registerProduct(Product product);
}

4-2. Productクラス

Factoryにて生成されるオブジェクトの基底となるクラスです。

Product.java
package framework;

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

4-3. IDCardFactoryクラス

Factoryクラスで定義されたメソッドを実装する具象クラスです。

IDCardFactory.java
package idcard;
import java.util.ArrayList;

import framework.Factory;
import framework.Product;

public class IDCardFactory extends Factory {

    private ArrayList<String> owners = new ArrayList<String>();

    protected Product createProduct(String owner) {
        return new IDCard(owner);
    }

    protected void registerProduct(Product product) {
        IDCard icCard = (IDCard)product;
        String owner = icCard.getOwner();
        owners.add(owner);
    }

    public ArrayList<String> getOwners() {
        return owners;
    }
}

4-4. IDCardクラス

Productクラスで定義されたメソッドを実装する具象クラスです。

IDCard.java
package idcard;
import framework.Product;

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;
    }
}

4-5. Mainクラス

メイン処理を行うクラスです。

Main.java
import framework.*;
import idcard.*;

public class Main {
    public static void main(String[] args) {
        Factory factory = new IDCardFactory();
        Product card1 = factory.create("山田");
        Product card2 = factory.create("鈴木");
        Product card3 = factory.create("佐藤");
        card1.use();
        card2.use();
        card3.use();
    }
}

4-6. 実行結果

山田のカードを作ります。
鈴木のカードを作ります。
佐藤のカードを作ります。
山田のカードを使います。
鈴木のカードを使います。
佐藤のカードを使います。

5. メリット

Factory/Productはframeworkパッケージ、IDCardFactory/IDCardはidcardパッケージに存在します。
frameworkパッケージでは、idcardパッケージをインポートしていません。つまり、frameworkパッケージでは、idcardパッケージに依存しない形になっています。
全く別の「製品」と「工場」を作ろうとした場合、frameworkパッケージの中身を修正する必要がなくなります。

6. GitHub

7. デザインパターン一覧

8. 参考

今回の記事、及びサンプルプログラムは、以下の書籍を元に作成させて頂きました。

大変分かりやすく、勉強になりました。感謝申し上げます。
デザインパターンやサンプルプログラムについての説明が詳細に書かれていますので、是非書籍の方もご覧ください。