まとめ
- オブジェクトを生成・返却するメソッドのインタフェースを定義する
- 実際にどのクラスを生成するかはサブクラスの実装|overrideに委ねる
別名
Virtual Constructor
モチベーション
-
世の中のプログラムフレームワークは抽象クラスを扱う
- フレームワーク利用者が具象クラスを定義して拡張できるようにしている
- フレームワークはどんな具象クラスが渡されるかわからないので、抽象クラス間の関係を管理する
-
フレームワークは、管理対象のクラスのオブジェクトの生成を担うこともある
- でも抽象クラスだから直接はインスタンシエートできない
- フレームワークは「いつ」オブジェクトを生成すべきかを知っている
- 「どの種類の」クラスのオブジェクトを生成すべきかはわからない → 分離してクライアントコードに委ねる
つかいどころ
- Creatorは生成対象の具体的なクラスを知らない
- ので、派生ConcreteCreatorに生成対象のクラスを特定してもらう
- Strategyパターンのように、生成対象が仕事を別のクラス(helper subclasses)に委譲している場合、どのhelper subclassと組み合わせて使うかの知識を一ヶ所にまとめたい
登場人物
-
Product
- 生成するオブジェクトのインタフェースを定義
-
ConcreteProduct
- Productの派生
-
Productに汎化できる程度には似通っている必要がある
- BuilderパターンにおけるProductは汎化しない。複雑で共通項が少なすぎるから
-
Creator
-
ファクトリメソッドを定義する
-
CreateProduct() : Product
とかそんなかんじCreateAndSetupProduct() : Product
の中で呼び出したりする(TemplateMethodパターン)
-
-
-
ConcreteCreator
- Creatorの派生
- ファクトリメソッドを実装する
功罪
- Product派生のいかなるConcreteProductクラスでもインスタンシエートできる
- ConcreteProductの数だけConcreteCreatorクラスを定義しないといけない
-
オブジェクト生成処理の前後等にhookをもうけることができる
- デフォルトなにもしない
- 生成したらダイアログを出すようoverrideする、とかできる
-
並列な継承木を結びつける
- BridgeパターンのImplementor、StrategyパターンのStrategyなど
- 「
ConcreteProductA
に対してはStrategy1
を使います」といった知識をCreator内にカプセル化できる
実装
2種類に大別できる
a. Creatorクラスは抽象クラス、ファクトリメソッドは抽象メソッド
- 基本のき
a. Creatorクラスは具象クラス、ファクトリメソッドは実装をもつ
- たとえば、Productは具象クラスで、Strategyに処理を委譲している場合
- Creator
のファクトリメソッドではProduct
の生成と、デフォルトのNullStrategy
の設定のみ行う
- ConcreteCreator
のファクトリメソッドのoverrideの中では、基底のファクトリメソッドを呼び出し、StrategyをConcreteStrategy
にすげ替える
ConcreteCreator増えすぎ問題に対処するバリアント
Creatorを具象クラスにして、下記を適用する
- ファクトリメソッドに引数を追加
どのProductを作るかをenumとかで指定する -
作るべきProductクラスをCreatorのメンバ変数に格納する
-
クラスが第一級オブジェクトである言語限定
- JSとか
-
-
ジェネリクス使う
-
C++のtemplateとか
- この場合、ソースコードが簡潔になるだけで、オブジェクトコードは
Creator<T>
クラスの具象化の数だけ増えるので注意
- この場合、ソースコードが簡潔になるだけで、オブジェクトコードは
-
用例
あらゆるフレームワーク
関連するパターン
-
AbstractFactoryパターン
- FactoryMethodパターンで実装されることがある
- 他の実装としては、Prototypeパターン等
-
TemplateMethodパターン
- 「基底では中身のないファクトリメソッドを呼び出し、派生でファクトリメソッドの実装を書く」というのは、TemplateMethodそのもの