pythonによるデザインパターン[Factory Method]
# Intro
この文章は結城 浩さんの「Java言語で学ぶデザインパターン入門」を、pythonで実装してみたサンプルコードです。
筆者の環境は以下の通りです。Python 3.6.3
まだ修行中の身なので間違いがあると思いますがご了承ください。 今回は「Factory Method」です。
# Summarise
本書のp46によると、 Factory Methodとは
スーパークラスで処理の枠組みを定め、サブクラスでその具体的内容を定めるようなデザインパターン
とあります。Templateパターンでは抽象クラスを作成し、それを具体的なクラスで実装しましたが、インスタンス生成の枠組みまでを抽象クラスで決定したい時にFactory Methodを用います。具体的に見た方が理解が早いので、見ていきましょう。
# Practice
## Specification
IDCardを作成するプログラムを作ります。 name
Fieldを登録して class IDCard
を作成し、 def use
メソッドで名前を表示します。
class IDCard
のインスタンスをそのまま作成してもいいのですが、今回はカードの所有者(class IDCard
のname
Field)を管理するとします。よって、 class IDCardFactory
という工場で、 owner
Fieldを定義し、そこにclass IDCard
のname
Fieldを登録していきます。
これを実現するようなプログラムを作成してください。ただし、今回は今後の拡張性を考えて抽象クラスを用いて、class IDCard
やclass IDCardFacotry
の振る舞いを抽象クラスで規定してください。
## Explanation
最初にclass IDCard
の抽象クラス、 class Product
を作成します。
このクラスはIDCardに限らず、何かの品物を表すクラスで、def use
というメソッドを持ちます。
次にclass IDCardFactory
の抽象クラス、 class Factory
を作成します。
このクラスは先ほど作成した class Product
を管理するクラスですowner
Fieldを持ち、
class Product
を作成する関数def create_product
class Product
の所有者(name
Field)を登録する関数def register_product
を持ちます。
重要なのはclass Factory
がclass Product
のインスタンスの生成・登録の枠組みまで決めていることです。これは前に紹介したTemplateパターンと大きく違う点です(Template Methodは処理の枠組みを決めるだけ)。Tempalte Methodについて詳しく知りたい方は以下を見てください。
それでは次に具体的なクラスを見ていきましょう。
class Product
を継承したclass IDCard
、class Factory
を継承したclass IDCardFactory
を作成します。とは、言っても先に抽象クラスで枠組みを決めておいたので、それに沿って具体的な実装をするだけです。
class IDCardFactory
の owners
FieldがList型になっており、そこに所有者の名前を登録します。抽象クラスに沿って実装すると、class IDCardFactory
がclass IDCard
のインスタンスの生成・登録を行なっていることがわかります。
## Sample Code
python3 factory.py 結城浩のカードを作成します。
とむらのカードを作成します。
佐藤花子のカードを作成します。
結城浩のカードを使います。
とむらのカードを使います。
佐藤花子のカードを使います
# Conclusion
私がこのデザインパターンを初めて知った時に下の2つの疑問が湧きました。
- 何でFactoryとProductに分けるのか?
- 何で抽象クラスをどっち共に作るのか?
昔の自分のために、それぞれに答えていきたいと思います。
- 何でFactoryとProductに分けるのか?
これは何かインスタンスがあって、それを管理したい時にFactoryとProductに分ける必要があります。
ってありますが、まあそれは理解できるとしても、実際でどのような場面で使われるのでしょうか?まだよくわからないです….。別に管理するだけだったら、Productのクラス変数の配列に入れるとか、他の方法がある気がするのですが… - 何で抽象クラスを両方共に作るのか?
これは1で説明したFactoryとProductの枠組みを抽象クラスで決定したいからです。今回はIDCardとIDCardFactoryだけですが、テレビを追加したい時は、class TV
とclass TVFactory
を追加するだけです。
重要なのは、class Factory
は具体的なクラス名(class IDCard
やclass TV
)を指定していないので、例え新しくテレビを追加しても抽象クラスはいじらなくてもいいのです。つまりclass Product
のインスタンス生成を、メソッド呼び出しを通して行うことで、具体的なクラス名による束縛から解放されているのです。
このようにclass Product
とclass Factory
のような抽象クラスを作ることで、インスタンス生成・登録の枠組みを決められるだけでなく、具体的なクラス名による束縛を受けなくて済むのです。
色々長々と語ってきましたが、いまいちFactory Methodは実践の場面でどこで使うのだろう???と思っています。でもTemplate Methodよりも、広い範囲でインスタンスの振る舞いを決定できるので、そのような場面がいつか来るのかなあ、と心に留めておきます。
# ref
- 「増補改訂版 Java言語で学ぶデザインパターン入門」 結城浩(著)第11版