3753817_s


本記事では、デザインパターンの名著である結城浩さんの『Javaで学ぶデザインパターン入門』を参考にFactory Method(ファクトリ・メソッド)をC++で実装していきます。




Factory Methodとは


Factory Methodとは、Template Methodをインスタンス生成の場面に適用したものです。

Factoryは、工場という意味です。

要するにFactory Methodとは、インスタンスを生成するための工場のようなデザインパターンだと思ってください。






Factory Methodの登場人物


Factory Methodは以下のようなクラス構成になっています。


factoryMethod


Product


Factory Methodで生成されるインスタンスが持つべきAPIを定義する抽象クラスです。

APIの具体的な実装は、ConcreateProductでクラスで行います。


Creator


Productを生成する抽象クラスです。

Crateorクラスは、Createメソッドで実際に生成する、ConcreteProductについては何も知りませんが、インスタンスを生成するメソッドを作ることでこの問題を解決しています。


ConcreteProduct


ConcreteProductは実際に生成される具体的な製品の役です。


ConcreteCreator


ConcreteCreatorは実際にConcreteProductを生成する役です。



C++による実装


今回は、IDカードを製造する工場というイメージでプログラムをFactory Methodを使用して実装していきます。

クラス構成は以下の通りです。


factoryMethodSample



Productクラス


Productクラスは抽象クラスとして実装していきます。


ヘッダファイル

#ifndef PRODUCT_H
#define PRODUCT_H

class Product{
public:
    virtual void use()=0;
};
#endif // PRODUCT_H



Factoryクラス


createメソッドでは、インスタンスを生成するcreateProductMethodを呼び出し、生成したインスタンスをregisterProductで登録するという処理を行います。

createメソッド以外の具体的な実装は子クラスで行います。今回の場合は、IDCardFactoryクラスが子クラスにあたります。

createMethodは継承先でオーバーライドされないようにfinalを使って宣言します。

ヘッダファイル

#ifndef FACTORY_H
#define FACTORY_H

#include <iostream>

class Product;

class Factory{
public:
    virtual Product* create(std::string ownerfinal;
    virtual Product* createProduct(std::string owner)=0;
    virtual void registerProduct(Product* product)=0;
};
#endif // FACTORY_H


ソースファイル

#include "Factory.h"
#include "Product.h"

Product* Factory::create(std::string owner){
    Productp = createProduct(owner);
    registerProduct(p);
    return p;
}






IDCardクラス


IDCardクラスはProductクラスを継承して作る、具体的な製品のクラスです。

今回は、useメソッドでカードを使い、getOwnerメソッドでカードの持ち主の名前を返します。

ヘッダファイル

#ifndef IDCARD_H
#define IDCARD_H

#include <iostream>
#include "Product.h"

class IDCard : public Product{
public:
    IDCard(std::string owner);
    ~IDCard();
    void use() final;
    std::string getOwner();
    
private:
    std::string m_owner;
};
#endif // IDCARD_H


ソースファイル

#include <iostream>
#include "IDCard.h"

IDCard::IDCard(std::string owner)
m_owner(owner)
{
    std::cout << owner << "のカードを作ります。" << std::endl;
};

IDCard::~IDCard(){};

void IDCard::use(){
    std::cout << m_owner << "のカードを使います。" << std::endl;
}

std::string IDCard::getOwner(){
    return m_owner;
}



IDCardFactoryクラス


IDCardFactoryクラスではcreateProductメソッドの具体的な実装を行っています。

このメソッドではIDCardのインスタンスを生成します。

また、registerOwnerでは生成したインスタンスを登録します。

ヘッダファイル

#ifndef IDCARDFACTORY_H
#define IDCARDFACTORY_H

#include <iostream>
#include <list>
#include "Factory.h"

class Product;

class IDCardFactory : public Factory{
public:
    IDCardFactory();
    ~IDCardFactory();
    Product* createProduct(std::string owner);
    void registerProduct(Product* product);
    std::list<std::stringgetOwners();
    
private:
    std::list<std::stringm_owners;
};
#endif // IDCARD_H


ソースファイル

#include "IDCardFactory.h"
#include "Product.h"
#include "IDCard.h"

IDCardFactory::IDCardFactory(){};

IDCardFactory::~IDCardFactory(){};

Product* IDCardFactory::createProduct(std::string owner){
    return new IDCard(owner);
}

void IDCardFactory::registerProduct(Product* product){
    m_owners.push_back(dynamic_cast<IDCard*>(product)->getOwner());
}

std::list<std::stringIDCardFactory::getOwners(){
    return m_owners;
}



main関数


今まで作成してきたクラスを実際に使っていきます。

ソースファイル

#include "Factory.h"
#include "Product.h"
#include "IDCardFactory.h"
#include "IDCard.h"

int main(void){
    Factory *factory = new IDCardFactory();
    Product *card1 = factory->create("としお");
    Product *card2 = factory->create("ひろし");
    Product *card3 = factory->create("花子");
    card1->use();
    card2->use();
    card3->use();

    return 0;
}


実行結果

としおのカードを作ります。
ひろしのカードを作ります。
花子のカードを作ります。  
としおのカードを使います。
ひろしのカードを使います。
花子のカードを使います。




まとめ


今回は、Template Methodを応用したFactory MethodはTemplate Methodを実装していきました。

似たようなクラスを複数個生成するときなどに便利なデザインパターンでした。

有効に活用できる場面を分析すれば、とても役にたつのでぜひ使ってみてください。