今日はデザインパターンの一つである、ファクトリメソッドについてまとめます。
スポンサードサーチ
ファクトリメソッドとは?
簡単に一行でまとめると、
インターフェースを介することで、オブジェクト生成を柔軟に行えるようにする。
といったものです。


おっしゃっていること分かります・・・ゆっくり見ていきましょう。
スポンサードサーチ
従来のオブジェクト生成方法
一般的にはオブジェクトを生成するときは、下記の様に行うと思います。
class *a_1= new ClassA();
class *a_2 = new ClassA();
問題なく、オブジェクトは生成できますが、これの問題点は、
具象クラスの名前を明示的に書くので、同じクラスのオブジェクトを複数生成したいときには、そのクラスの名前がコードの複数個所に出てくることにあります。それゆえに、コードの拡張や保守の観点からめんどくさくなります。
具象クラスを明示してオブジェクトを生成するので、
・新しくクラスを追加するとき
・使用するクラスを切り替えたいとき
に具象クラスが出てくる個所をすべて修正する必要がある。
以上を踏まえて、ファクトリメソッドでは、
インターフェースを通して、オブジェクトの生成を行うことで、生成される側と生成する側の結びつきを弱くすることで、クラスの切り替えや新規クラスの追加を柔軟に行っていきます。

何言っているかわからないと思います。具体例を見ながら進めてきましょう。
スポンサードサーチ
適用場面
現状-ダミークラスを使って開発を進めて、後で実際のクラスに切り替えたい
といった状況があったとします。後で、実際に開発されたクラスを使っていくとします。
具体例として、Webカメラから画像を取得するクラスについて考えます。
現在はWebカメラから画像を取れないので、一旦はローカルにある画像を読み込んで、処理していくことにします。
・後々はwebカメラの画像を撮像して、その画像を取得していく。
・現在はwebカメラの画像が取れないので、一旦は画像を読み込んで進めていく。

行ってみよう!
ファクトリメソッドを使う前
using namespace std;
class ReadImageObject {
public:
ReadImageObject() {cout<< "画像を読み込みました。"; }
};
int main() {
ReadImageObject *temp = new ReadImageObject("path");
}
ファクトリメソッドを使う前は上記の様なコードになります。これの何に問題があるかわかりますか?
これの問題点は、後々にGetWebCameraObjectが作られた時に、
ReadImageObject *temp = new ReadImageObject();
を
GetWebCameraObject *temp = new GetWebCameraObject ();
と変更しないといけません。これが一行二行であれば問題ございません。もし、これが大きなアプリケーションの場合、相当な個所を修正しなければなりません。
これを解決するのが、ファクトリメソッドです。
スポンサードサーチ
ファクトリメソッドを適用する。
using namespace std;
class DataObject {
public:
static DataObject* create();
};
class ReadImageObject :public DataObject {
public:
ReadImageObject() {cout<< "画像を読み込みました。"; }
};
DataObject* DataObject::create(){
return new ReadImageObject();
}
int main() {
DataObject* temp = DataObject::create();
}
上のコードがファクトリメソッドです。前後の比較では、
■適用前
・newを使用して、オブジェクトを取得。
・画像読み込みするクラス(ReadImageObject)の名前をクライアント側で明示的に指定。
■適用後
・メソッドの呼び出し側でオブジェクトを取得する。
・クライアント側では、Webカメラ(GetWebCameraObject)か画像読み込み(ReadImageObject)なのか気にする必要がない
では、実際にWebカメラ読み込みクラスが開発されました。その時のクライアント側の動作はこうなります。
適用前
using namespace std;
class ReadImageObject {
public:
ReadImageObject() {cout<< "画像を読み込みました。"; }
};
class GetWebCameraObject {
public:
GetWebCameraObject() { cout << "Webカメラから画像を読み込みました。"; }
};
int main() {
//ReadImageObject* temp = new ReadImageObject("path");
GetWebCameraObject* temp = new GetWebCameraObject();
}
適用後
using namespace std;
class DataObject {
public:
static DataObject* create();
};
class ReadImageObject :public DataObject {
public:
ReadImageObject() { cout << "画像を読み込みました。"; }
};
class GetWebCameraObject :public DataObject {
public:
GetWebCameraObject() { cout << "Webカメラを読み込みました"; }
};
DataObject* DataObject::create() {
//return new ReadImageObject();修正箇所
return new GetWebCameraObject();
}
int main() {
DataObject* temp = DataObject::create();
}
どうでしょうか?見ていただくとわかるように、クライアント側は一切の変更を加えていません。
クラスの提供者側が変更を加えただけですので、クライアント側の修正はこの場合はありません。また、あったとしても適用前に比べてはるかに少なくなります。
まとめ
以下まとめです。
■適用前
・newを使用して、オブジェクトを取得。
・画像読み込みするクラス(ReadImageObject)の名前をクライアント側で明示的に指定。
■適用後
・メソッドの呼び出し側でオブジェクトを取得する。
・クライアント側では、Webカメラ(GetWebCameraObject)か画像読み込み(ReadImageObject)なのか気にする必要がない
大変便利なファクトリメソッドについて紹介しました。ぜひ、この記事が参考になれば幸いです。
は??