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 IDCardname Field)を管理するとします。よって、 class IDCardFactory という工場で、 owner Fieldを定義し、そこにclass IDCardname Fieldを登録していきます。

これを実現するようなプログラムを作成してください。ただし、今回は今後の拡張性を考えて抽象クラスを用いて、class IDCardclass 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 Factoryclass Product のインスタンスの生成・登録の枠組みまで決めていることです。これは前に紹介したTemplateパターンと大きく違う点です(Template Methodは処理の枠組みを決めるだけ)。Tempalte Methodについて詳しく知りたい方は以下を見てください。

それでは次に具体的なクラスを見ていきましょう。

class Product を継承したclass IDCardclass Factory を継承したclass IDCardFactoryを作成します。とは、言っても先に抽象クラスで枠組みを決めておいたので、それに沿って具体的な実装をするだけです。

class IDCardFactoryowners FieldがList型になっており、そこに所有者の名前を登録します。抽象クラスに沿って実装すると、class IDCardFactoryclass IDCard のインスタンスの生成・登録を行なっていることがわかります。

## Sample Code

python3 factory.py 結城浩のカードを作成します。
とむらのカードを作成します。
佐藤花子のカードを作成します。
結城浩のカードを使います。
とむらのカードを使います。
佐藤花子のカードを使います

# Conclusion

私がこのデザインパターンを初めて知った時に下の2つの疑問が湧きました。

  1. 何でFactoryとProductに分けるのか?
  2. 何で抽象クラスをどっち共に作るのか?

昔の自分のために、それぞれに答えていきたいと思います。

  1. 何でFactoryとProductに分けるのか?
    これは何かインスタンスがあって、それを管理したい時にFactoryとProductに分ける必要があります。
    ってありますが、まあそれは理解できるとしても、実際でどのような場面で使われるのでしょうか?まだよくわからないです….。別に管理するだけだったら、Productのクラス変数の配列に入れるとか、他の方法がある気がするのですが…
  2. 何で抽象クラスを両方共に作るのか?
    これは1で説明したFactoryとProductの枠組みを抽象クラスで決定したいからです。今回はIDCardとIDCardFactoryだけですが、テレビを追加したい時は、 class TVclass TVFactory を追加するだけです。
    重要なのは、 class Factory は具体的なクラス名( class IDCardclass TV )を指定していないので、例え新しくテレビを追加しても抽象クラスはいじらなくてもいいのです。つまり class Productのインスタンス生成を、メソッド呼び出しを通して行うことで、具体的なクラス名による束縛から解放されているのです。
    このようにclass Productclass Factory のような抽象クラスを作ることで、インスタンス生成・登録の枠組みを決められるだけでなく、具体的なクラス名による束縛を受けなくて済むのです。

色々長々と語ってきましたが、いまいちFactory Methodは実践の場面でどこで使うのだろう???と思っています。でもTemplate Methodよりも、広い範囲でインスタンスの振る舞いを決定できるので、そのような場面がいつか来るのかなあ、と心に留めておきます。

# ref

--

--