セダンとバンを作る工場を作成するので、2つの工場を作成する必要があります。
ですが、2つの工場は「車を作る」という点で類似したものだと考えられます。
こういう時は、「車を作る」クラスをスーパークラスとして、
セダンとバンを作る工場をサブクラスとした方が適切です。
また、セダンとバンについても同じことが言えます。これらは全く同じではありませんが、
2つとも「車」ですよね。なので、こちらも「車」を表すクラスを継承して、セダンとバンを
表すクラスを作成します。
では、ここまでで必要なクラスを洗い出しましょう。
Factory |
「車を作る工場」を表す抽象クラス |
SedanFactory |
Factoryをスーパークラスとする「セダンを作る工場」を表すクラス |
VanFactory |
Factoryをスーパークラスとする「バンを作る工場」を表すクラス |
Car |
「車」を表す抽象クラス |
Sedan |
Carをスーパークラスとする「セダン」を表すクラス |
Van |
Carをスーパークラスとする「バン」を表すクラス |
ここで考えなければならないのは、工場での車を作る処理についてです。
工場が車を作ってくれるんですから、ユーザが車をnewするのは相応しくないですよね。
せっかく工場を作ったんですから、工場から車を取得したいものです。
そのためには、工場内で対応する車のインスタンスを返すメソッドを定義しなければなりません。
このようなパターンがFactory Methodパターンです。
これは現実世界でも同じです。車を運転する人が車を作るわけではありません。
工場で作られた車をバイヤーから買うわけですね。
ただし、このFactory Methodを「newするのが相応しくないから使う」というふうに考えるのは
適切ではありません。この例のように、「"工場"が"車"を作る」などというクラス間に絶対的な
関係がない場合は使うべきではありません。逆にきちんとした関係がある場合には、積極的に使うべきです。
その理由は、ソースを見てもらえれば分かるかと思いますが、Mainクラスの中で
乗る車をセダンからバンに変更しています。ところが、変更後にnewが必要なのは
Factoryクラスの変数factoryに対してだけで、車を作成するメソッドはそのまま流用できます。
変更箇所が少ないのは、単純に手間だけでなくプログラムの可読性やを高める上でも有効です。
ユーザは工場を変更することだけに集中すればよく、車のインスタンス生成などを気にかける必要はないのです。
ちなみに、抽象クラスであるFactoryクラスでは、
Template Methodパターンを適用しています。
Factory Methodはいわば、インスタンス生成に対してTemplate Methodを適用したものだと考えられます。
|