本記事では、デザインパターンの名著である結城浩さんの『Javaで学ぶデザインパターン入門』を参考にFactory Method(ファクトリ・メソッド)をC++で実装していきます。
【目次】
〇Factory Methodとは
〇Factory Methodの登場人物
・Product
・Creator
・ConcreteProduct
・ConcreteCreator
〇C++による実装
・Productクラス
・Factoryクラス
・IDCardクラス
・IDCardFactoryクラス
・main関数
〇まとめ
Factory Methodとは
Factory Methodとは、Template Methodをインスタンス生成の場面に適用したものです。
Factoryは、工場という意味です。
要するにFactory Methodとは、インスタンスを生成するための工場のようなデザインパターンだと思ってください。
Factory Methodの登場人物
Factory Methodは以下のようなクラス構成になっています。
Product
Factory Methodで生成されるインスタンスが持つべきAPIを定義する抽象クラスです。
APIの具体的な実装は、ConcreateProductでクラスで行います。
Creator
Productを生成する抽象クラスです。
Crateorクラスは、Createメソッドで実際に生成する、ConcreteProductについては何も知りませんが、インスタンスを生成するメソッドを作ることでこの問題を解決しています。
ConcreteProduct
ConcreteProductは実際に生成される具体的な製品の役です。
ConcreteCreator
ConcreteCreatorは実際にConcreteProductを生成する役です。
C++による実装
今回は、IDカードを製造する工場というイメージでプログラムをFactory Methodを使用して実装していきます。
クラス構成は以下の通りです。
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 owner) final;
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){
Product* p = 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::string> getOwners();
private:
std::list<std::string> m_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::string> IDCardFactory::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を実装していきました。
似たようなクラスを複数個生成するときなどに便利なデザインパターンでした。
有効に活用できる場面を分析すれば、とても役にたつのでぜひ使ってみてください。