Factory Method パターン [Java]

GoFデザインパターンについて学んでます.

今回は「Factory Method」パターンについて学びます.

Factory Method

インスタンス生成の工場です.
newを使わずにインスタンス化のロジックを子クラスに委譲する手段を提供します.

Productクラス(Product抽象クラス)

このパターンで生成されるインスタンスが持つべきAPIを定める抽象クラス.

package factory.framework;

/**
 * 「製品」を表現したクラス
 * @author xrdnk
 *
 */
public abstract class Product {

    public abstract void use();
}

Factoryクラス(Creator抽象クラス)

Product役を生成する抽象クラス.
newによる実際のインスタンス生成を,インスタンス生成のためのメソッド呼び出しに替えることで,
具体的なクラス名による束縛からスーパークラスを解放することができる.

package factory.framework;

/**
 * 製品を作成する「工場」クラス
 * インスタンスの作成はこの抽象クラスが担う
 * @author xrdnk
 *
 */
public abstract class Factory {

    /**
     * 製品を作り,登録するメソッド
     * @param owner
     * @return 製品
     */
    public final Product create(String owner) {
        Product p = createProduct(owner);
        registerProduct(p);
        return p;
    }

    /**
     * 製品を作るメソッド
     * @param owner
     * @return 製品
     */
    protected abstract Product createProduct(String owner);

    /**
     * 製品を登録するメソッド
     * @param product
     */
    protected abstract void registerProduct(Product product);
}

IDCard(Product具象クラス)

package factory.framework;

/**
 * 「製品」を表現したクラス
 * @author xrdnk
 *
 */
public abstract class Product {

    public abstract void use();
}

IDCardFactory(Creator具象クラス)

package factory.idcard;

import java.util.ArrayList;
import java.util.List;

import factory.framework.Factory;
import factory.framework.Product;


public class IDCardFactory extends Factory {

    /** 所有者リスト */
    private List<String> owners = new ArrayList<>();

    /** インスタンス生成 */
    @Override
    protected Product createProduct(String owner) {
        return new IDCard(owner);
    }

    /** リストに生成したインスタンスを登録 */
    @Override
    protected void registerProduct(Product product) {
        owners.add(((IDCard) product).getOwner());
    }

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

}

Mainクラス(動作確認用)

package factory;

import factory.framework.Factory;
import factory.framework.Product;
import factory.idcard.IDCardFactory;

/**
 * 動作テスト用クラス
 * @author xrdnk
 *
 */
public class Main {
    public static void main(String[] args) {
        Factory factory = new IDCardFactory();
        Product card1 = factory.create("suzuki");
        Product card2 = factory.create("toyota");
        Product card3 = factory.create("mitsubishi");
        System.out.println("========================");
        card1.use();
        card2.use();
        card3.use();
    }
}

結果はこんな感じになります.

suzukiのカードを作ります.
toyotaのカードを作ります.
mitsubishiのカードを作ります.
========================
suzukiのカードを使います.
toyotaのカードを使います.
mitsubishiのカードを使います.