Skeleton of GOF's Design Pattern


!

FACTORYMETHOD の骸骨

FACTORYMETHOD

抽象クラスのみを扱うクライアントやフレームワークでは 関連するオブジェクトの生成を特定することができません。そのような問題を解決するのが、このパターンです。

抽象的な例えになってしまいますが、鶏が鶏卵を産むということを、鳥が卵を産むというだけで記述するためのパターンです。鶏と鶏卵、鶉と鶉卵のようにサブクラス同士のパラレルなクラス階層ができるのが、このパターンの特徴です。このとき、鳥にあたるものは Creator と呼び、卵は Product と呼びます。

FACTORYMETHODは、仮想コンストラクタと呼ばれています。コンストラクタは仮想関数にすることはできませんが、FACTORYMETHODを使えば、抽象クラスからコンストラクタを呼ぶことができます。


■ 『FACTORYMETHODの骸骨』の構造


■ 『FACTORYMETHODの骸骨』 プログラム・コード

□ Java2版
// Copyright(C) 2000-2003 Yoshinori Oota All rights reserved.

public class FactoryMethodSample {
    static public Creator Create(String str) {
        if (str.equals("A")) {
            return new CreatorA();
        } else if (str.equals("B")) {
            return new CreatorB();
        }
        return null;
    }

    static public void main(String[] args) { 
        Creator creator1 = Create("A"); // クライアントコードは、ConcreteCreatorが、
        Creator creator2 = Create("B"); // AかBか、意識する必要はない
		
        Product product1 = creator1.FactoryMethod();
        Product product2 = creator2.FactoryMethod();

        product1.Operation();
        product2.Operation();
    }
}

abstract class Creator { 
    abstract public Product FactoryMethod();
}
				
class CreatorA extends Creator { 
    public Product FactoryMethod() { 
        return new ProductA(); 
    } 
}

class CreatorB extends Creator { 
    public Product FactoryMethod() { 
        return new ProductB(); 
    } 
}

abstract class Product { 
    abstract void Operation(); 
}

class ProductA extends Product { 
    public void Operation() { 
        System.out.println("ProductA"); 
    } 
}

class ProductB extends Product { 
    public void Operation() { 
        System.out.println("ProductB"); 
    } 
}

○ C++版
// Copyright(C) 2003 Yoshinori Oota All rights reserved.

#include <iostream>
using namespace std;

class Product {
public:
    Product();
    virtual ~Product();
    virtual void Operation() = 0;
};

class Creator {
public:
    Creator();
    virtual ~Creator();
    virtual Product* FactoryMethod() = 0;
};

class ProductA : public Product {
public:
    ProductA();
    virtual ~ProductA();
    virtual void Operation();
};

class ProductB : public Product {
public:
    ProductB();
    virtual ~ProductB();
    virtual void Operation();
};

class CreatorA : public Creator {
public:
    CreatorA();
    virtual ~CreatorA();
    virtual Product* FactoryMethod();
};

class CreatorB : public Creator {
public:
    CreatorB();
    virtual ~CreatorB();
    virtual Product* FactoryMethod();
};



Product::Product() { }
Product::~Product() { }

ProductA::ProductA() { }
ProductA::~ProductA() { }
void ProductA::Operation() {
    cout << "ProductA" << endl;
}

ProductB::ProductB() { }
ProductB::~ProductB() { }
void ProductB::Operation() {
    cout << "ProductB" << endl;
}


Creator::Creator() { }
Creator::~Creator() { }

CreatorA::CreatorA() { }
CreatorA::~CreatorA() { }
Product* CreatorA::FactoryMethod() {
    return new ProductA();
}

CreatorB::CreatorB() { }
CreatorB::~CreatorB() { }
Product* CreatorB::FactoryMethod() {
    return new ProductB();
}


Creator* Create(char sw) {
    if (sw == 'A') {
        return new CreatorA();
    } else if (sw == 'B') {
        return new CreatorB();
    }
}

int main() {
    Creator* creator1 = Create('A');    // クライアントコードは、ConcreteCreatorが、
    Creator* creator2 = Create('B');    // AかBか、意識する必要はない

    Product* product1 = creator1->FactoryMethod();
    Product* product2 = creator2->FactoryMethod();

    product1->Operation();
    product2->Operation();

    delete product1;
    delete product2;
    delete creator1;
    delete creator2;

    return 0;
}

○ C版
/* Copyright (C) 2009 Yoshinori Oota All rights reserved. */
#include <stdio.h>
#include <stdlib.h>

enum PRODUCT_TYPE { PRODUCT_A, PRODUCT_B };
enum CREATOR_TYPE { CREATOR_A, CREATOR_B };

/* Product Interface */
struct Product {
    void (* Operation)();
};

struct Product* New_Product(enum PRODUCT_TYPE type);
void Delete_Product(struct Product* product);
void ProductA_Operation();
void ProductB_Operation();

/* Creator Interface */
struct Creator {
    struct Product* (*FactoryMethod)();
};
struct Creator* New_Creator(enum CREATOR_TYPE type);
void Delete_Creator(struct Creator* creator);
struct Product* CreatorA_FactoryMethod();
struct Product* CreatorB_FactoryMethod();

/* Product Class Implementaion */
struct Product* New_Product(enum PRODUCT_TYPE type) {
    struct Product* product = NULL;
    product = (struct Product*)malloc(sizeof(struct Product));
    switch (type) {
    case PRODUCT_A:
        product->Operation = &ProductA_Operation;
        break;
    case PRODUCT_B:
        product->Operation = &ProductB_Operation;
        break;
    }
    return product;
}

void Delete_Product(struct Product* product) {
    if (product == NULL) {
        return;
    }
    free (product);
    product = NULL;
    return;
}

void ProductA_Operation() {
    printf("Hello\n");
    return;
}

void ProductB_Operation() {
    printf("Bonjour\n");
    return;
}

/* Create Class Implementation */
struct Creator* New_Creator(enum CREATOR_TYPE type) {
    struct Creator* creator = NULL;
    creator = (struct Creator*)malloc(sizeof(struct Creator));
    switch (type) {
    case CREATOR_A:
        creator->FactoryMethod = &CreatorA_FactoryMethod;
        break;
    case CREATOR_B:
        creator->FactoryMethod = &CreatorB_FactoryMethod;
        break;
    }
    return creator;
}

void Delete_Creator(struct Creator* creator) {
    if (creator == NULL) {
        return;
    }
    free(creator);
    creator = NULL;
    return;
}

struct Product* CreatorA_FactoryMethod () {
    return New_Product(PRODUCT_A);
}

struct Product* CreatorB_FactoryMethod () {
    return New_Product(PRODUCT_B);
}

struct Creator* Create(char sw) {
    if (sw == 'A') {
        return New_Creator(CREATOR_A);
    } else if (sw == 'B') {
        return New_Creator(CREATOR_B);
    }
    return NULL;
}

int main() {
    struct Creator* creator1 = NULL;
    struct Creator* creator2 = NULL;
    struct Product* product1 = NULL;
    struct Product* product2 = NULL;

    creator1 = Create('A');    // クライアントコードは、ConcreteCreatorが、
    creator2 = Create('B');    // AかBか、意識する必要はない

    product1 = creator1->FactoryMethod();
    product2 = creator2->FactoryMethod();

    product1->Operation();
    product2->Operation();

    Delete_Product(product1);
    Delete_Product(product2);
    Delete_Creator(creator1);
    Delete_Creator(creator2);

    return 0;
}


改訂履歴

2009.2.15 C言語版を追加
     
     

ご意見、ご感想はこちらまで。

Copyright(C) 2000-2009 Yoshinori Oota All rights reserved.

本ホームページのリンクは自由です。複製、転載される場合は、必ず著者までご連絡をください。