ようこそ。睡眠不足なプログラマのチラ裏です。

デザインパターン 第1回「FactoryMethodパターン」

デザインパターンとは、オブジェクト指向プログラミングにおいて
再利用可能な汎用的設計パターンのことを指します。


プログラマの世界では、様々なデザインパターンが知られていますが、
その中でもとりわけ有名なのが「GoFデザインパターン」です。
GoF(ゴフ)とは、そのデザインパターンをまとめた4人のことであり、”The Gang Of Four(4人の奴等)”の略です。*1



彼ら4人は、オブジェクト指向プログラミングに役立つデザインパターンを持ち寄り、
それらを本にまとめました*2。この本は、通称「GoF本」と呼ばれ、日本語にも翻訳されています。
この本の中に示された23種類のデザインパターンが、いわゆるGoFデザインパターンと呼ばれるものです。


では、今回はその中から「FactoryMethodパターン」をぬるーく解説します。


FactoryMethodパターンの概要■
オブジェクトを作成するときのインターフェイスだけを規定して、
実際にどのクラスをインスタンス化するかはサブクラスが決定するようにするパターン。
同じ種類のモノなら、同じように作れるようにしておこうという考え方。


FactoryMethod(工場メソッド)」と呼ばれるパターンは、
その名のとおり、工場のような役割を果たすメソッドを用意し、
そのメソッドで、サブクラスをインスタンス化して返してもらおうとするパターンです。
どんなときにそのようなメソッドが必要なのかと言うと、
一緒に使ってほしいオブジェクトを確実に用意する必要がある場合です。
ということであれば、一緒に使う機能を1つのクラスにまとめてしまえばいいじゃないか!と思われるかもしれませんが、
一緒にまとめてしまうと、クラスの役割が不明確となり、意味的に不自然なクラスになってしまう恐れがあります。
1つのクラスにいろいろな機能を盛り込み過ぎると、保守性・拡張性に欠けた、質の悪いクラス*3になってしまいます。



わかりにくいメタファとなるが、ここでは「ジョジョの奇妙な冒険」を題材とします。


空条承太郎クラス」と「ディオクラス」があるとします。能力者とスタンドはペアであるため、
それぞれ「スタープラチナクラス」および「ザ・ワールドクラス」と一緒に使って欲しいとします。
空条承太郎クラスのメンバに、スタープラチナクラスのインスタンスを返すCreaetStarPlatinum( )メソッドを用意します。
ディオクラスのメンバに、ザ・ワールドクラスのインスタンスを返すCreateTheWorld( )メソッドを用意します。
これによって、一緒に使ってほしいクラスを確実に生成することができます。



しかし、このままでは、クラスを使う利用者(開発者)から「こんなん使いづれえよ」と文句を言われるだろう。
クラスごとに名前の異なるCreateStarPlatinum( )やCreateTheWorld( )というメソッドを覚えるのがいちいち面倒だからです。
例えば、花京院典明クラス(ハイエロファントグリーン)や、ポルナレフクラス(シルバーチャリオッツ)などが増えると厄介になりそうだ。
そんなとき、どのオブジェクトが生成されるかは分からないが、
どのクラスでも同じCreateStand( )という名前のメソッドを呼びさえすれば、
利用者(開発者)が意識しなくても、必ず適切なペアが得られる仕組みができると良さそうだ。



スタープラチナオブジェクトでもザ・ワールドオブジェクトでも、どちらでも返せるCreateStand( )メソッドを実現するためには、
スタープラチナクラスとザ・ワールドクラスを汎化*4したスーパークラスを定義しておく必要があります。
(あるいは、同一のインターフェイスに属するようにクラスを定義する方が望ましいかもしれません。)
CreateStand( )メソッドの戻り値をスーパークラス(あるいはインターフェイス)にしておけば、
ポリモーフィズム(多態性)を活かして、どちらのオブジェクトでも返すことができる。



さらに、空条承太郎クラスとディオクラスには、同名のCreateStand( )メソッドを確実に持たせるようにしましょう。
そのためには、CreateStand( )メソッドを持つ抽象クラスを作り、それを空条承太郎クラスとディオクラスが継承し、
それぞれCreateStand( )メソッドの処理内容を適切にオーバーライド(上書き変更)すればよい。
そして、それぞれのクラスのCreateStand( )メソッドで適切なオブジェクトを返すようにする。このような手法を、FactoryMethodパターンと言う。

FactoryMethodパターンのまとめ

この、オブジェクトを生成して返すメソッドというアイディアは、既に使い古されたパターンではあるが、
このような設計パターンを利用したことのない人にとっては、画期的なアイディアであり、
オブジェクト指向の利点を活かす上で大変有意義なヒントとなるだろう。ぜひ有効活用してもらいたい。

FactoryMethodパターンは、どのクラスとどのクラスを一緒に使えば良いのか混乱してしまいそうな場合に効果を発揮しそうです。
あるいは、プロパティに応じて異なる振る舞いを持たせたいクラスがあるとき、
外部のサブクラスにその振る舞いを委譲させたい場合なんかにも、このパターンが適用できそうな感じですな^^
ただしこの手法は、クラスの関連性を複雑にしまう節もあるので、注意が必要だお(`・ω・´)


オマケ
FactoryMethodパターン - VB.NET - 雑なサンプルソース

*1:エリック・ガンマ、リチャード・ヘルム、ラルフ・ジョンソン、ジョン・ブリシディースの4人を指しています。

*2:Design Patterns : Elements of Reusable Object Oriented Software(1995年発刊)

*3:腐っているクラス

*4:汎化は、オブジェクト指向プログラミングでは、「継承」として表現されます。