Factory Method パターンを考えます。

デザインパターンを調べ始めた経緯はこちらです。

他のパターンはこちらです。

今回もこちらの本を読み解いていきます。

オブジェクト指向における再利用のためのデザインパターンhttps://www.amazon.co.jp/dp/4797311126/ref=cm_sw_em_r_mt_dp_CHFA3VH148WCATYTGCB7?_encoding=UTF8&psc=1

Factory Method とは日本語に直すとどのような意味になるのでしょうか?

Factoryとは、
工場、製造所

引用元URL:https://ejje.weblio.jp/content/factory

Methodとは、
(教授法・研究などの論理的で組織立った)方法、方式、(一定の)順序、筋道、秩序、規則正しさ、きちょうめん

引用元URL:https://ejje.weblio.jp/content/method

直訳では、工場的な方法・工場的な方式・工場的な道筋…というような意味となりそうです。


本でのカタログにあるFactory Method パターンは、パターンの目的から始まります。そして、パターンを適用する動機として仮の問題を想定し、その解決策がFactory Method パターンであることを示します。その後、パターンの有効な条件・構造・特徴・実装・サンプルコード・使用例・関連するパターンと内容が続きます。

今回は"特徴"までを考えていきます。

※かなり紆余曲折することや誤った解釈をする可能性があります。その際は是非コメントをお待ちしています。よろしくお願いします。

でははじめます。

本の項目通りに進めずにFactory Method パターンを自身が理解した過程で再構成しています。

Factory Method パターンの目的

オブジェクトを生成するときのインタフェースだけを規定して、実際にどのクラスをインスタンス化するかはサブクラスが決めるようにする。Factory Methodパターンはインスタンス化をサブクラスに任せる。

やはり難しいと思ってしまうのは諸所に出てくるカタカナのせいでしょうか。

Factory Method パターンの別名の翻訳を行ったところ少し理解が進んだのでこちらも紹介します。

別名:Virtual Constructor

直訳は仮想的なコンストラクタとなります。

コンストラクタ(英: constructor)は、オブジェクト指向のプログラミング言語で新たなオブジェクトを生成する際に呼び出されて内容の初期化などを行なう関数あるいはメソッドのことである。

引用先URL:https://ja.wikipedia.org/wiki/コンストラクタ

つまり最終的な翻訳としては下記のようになると思います。

新たなオブジェクトを生成する際に呼び出されて内容の初期化などを仮想的に行なう仕掛け。

結構いい感じです。オブジェクトって?と聞かれるとそれを説明する能力を自身が持ち合わせていないことが申し訳ないですが、そういったオブジェクト指向と題されているそのオブジェクトさえ説明できるようになっていきたいです。(決意表明でごまかす。。。)

”内容の初期化などを仮想的に行なう” ここが少し難解のように思えます。

雰囲気としては、継承もとのクラスにある仕掛け(役割・ロジック)を別のクラス(多分サブクラス)で新規のオブジェクトを生成するときに継承しているクラスの仕掛けの初期化などもやってしまう。

という感じでしょうか。だんだん文章ではわかりづらくなってきました。

Factory Method パターンの構造

画像1

引用先URL:http://www.cs.unc.edu/~stotts/GOF/hires/pat3cfso.htm

イメージ図を用意しました。

「パンをやく製法」を"工場の製法(Factory Method)"として丸パンやココアパンを生み出します。

PNGイメージ-7F7073AF6165-1

パンCreator (Creator) : パンをやく製法(Factory Method)
・こねて、はっこうさせて、やいてといった「パンをやく製法」を定義する。

丸パン担当Creator (ConcreteCreator)
・実際の丸パンをやく人 (return new ConcreteProduct)

ココアパン担当Creator (ConcreteCreator)
・実際のココアパンをやく人 (return new ConcreteProduct)

パンをやく製法 (Product)
・こねる、はっこうさせる、やくということも行うことができるのでパンも生み出せる。

実際の丸パン製法 (ConcreteProduct)
・「パンをやく製法」に加えて丸くする方法を加える。結果として丸パンが生み出される。

実際のココアパン製法 (ConcreteProduct)
・「パンをやく製法」に加えてココアパウダーをかける方法を加える。結果としてココアパンが生み出される。


このように「パンをやく製法」というFactory Methodつまり工場の製法を中心に「丸パン」や「ココアパン」をcreateつまり作る担当者が実物にしていくという流れです。

構成要素をまとめます。
Productクラス:パンをやく製法
「factory methodが生成するオブジェクトのインターフェース」(情報を交換するための共有境界・やり取りする部分)を定義します。
「パンをやく製法」そのものであり、場合によってパンを生み出すこともできるクラス。

ConcreteProductクラス:実際の丸パン製法・実際のココアパン製法
「Productクラスのインターフェースを定義」します。
「パンをやく製法」に固有の手順を加えて製法とするクラス。ConcreteCreatorクラスに呼ばれてパンをやく。

Creatorクラス:パンをやく製法を持つクラス
「Product型のオブジェクトを返すfactory methodを宣言」します。また、factory methodのデフォルトの定義として、ConcreteProductオブジェクトを返すようにすることもできます。
factory methodを呼び出して、Productオブジェクトを作成します。

「〇〇パンをやく製法」型を返す、"工場の製法"を宣言するクラス。デフォルトで呼ばれると「パンをやく製法」そのもの(ConcreteProductオブジェクト)つまりパンを返すようにすることもできる。
「パンをやく製法」を呼び出して、「〇〇パンをやく製法」(Productオブジェクト)を作成する。

ConcreteCreatorクラス:
パンをやく製法を聞いた丸パン担当Creator, ココアパン担当Creator
ConcreteProductクラスを返せるように、factory methodを継承します。
実際のパンを焼けるように、「パンをやく製法」を継承する人。

Factory Method パターンの特徴

1. サブクラスに"きっかけ"を与える。
Factory Method パターンの特徴として「クラス内部でオブジェクトを生成する場合、直接生成するよりもfactory methodを使う方が柔軟性を高め」られます。
またこの柔軟性は「factory methodは、オブジェクトを拡張する場合の」きっかけをサブクラスに与えているともいえます。

パンの例で考えるとサブクラスは「パンをやく製法」を継承することでその製法を利用した別の"パンをやく製法"を作ることができます。そしてfactory methodつまり「工場の製法」は抽象的ではなく、デフォルトの実装として例えば「パンをやく製法」であれば”パン”そのものを作れるように、具体的な実装も与えることができます。

2. 並列クラス階層と接続する。
今までの例では、factory methodはCreatorのオブジェクトのみから呼び出されます。

しかし、このような使い方に限定されているわけではなく、特に並列にクラス階層が存在する場合にクライアントにとってfactory methodは有効です。
並列クラス階層は、あるクラスがその─役割を正常に実行する─責任の一部を別のクラスに委譲する場合に発生します。

「パンをやく製法」の例で考えると、惣菜パンを焼きたいとします。すると途端に工程が増え、例えば内部にクリームシチューソースを加えたシチューパンや、内部にカレーを加えたカレーパンでは、どちらも"パンをやく製法"とは別の工程が必要なほかシチューの素とカレー粉を間違えると大変です。

このようなときに役立つのがManipulatorクラスです。Manipulatorは「マジックハンド・遠隔操作」という意味を持ちます。

画像3

引用先URL:http://www.cs.unc.edu/~stotts/GOF/hires/pat3cfso.htm

イメージ図を用意しました。

PNGイメージ-46B509CAD5B7-1

パンをやく製法(Product)
・クライアントがパンの種類に応じてManipulator"マジックハンド"を使えるようにfactory MethodとしてManipulatorを加えておきます。

シチューパンをやく製法(ConcreteProduct)
・パンをやく製法に"内部に空洞をつくる"という手順を加えて、シチューManipulatorを呼びます。

カレーパンをやく製法(ConcreteProduct)
・パンをやく製法に"内部に空洞をつくる"という手順を加えて、カレーManipulatorを呼びます。

Manipulator
・サブクラスの持つ工程を一通り備えておきます。具材を入れて、煮込みます。なので今回のManipulatorはこのままだと味がありません笑。

シチューManipulator
・具材を入れ、シチューの素を入れて、煮込みます。

カレーManipulator
・具材を入れ、カレー粉を入れ、煮込みます。


このように "パンをやく製法"factory method ではできないことを─パンを焼きながらマジックハンドでシチューを作るように(できるかは知らない笑)─Manipulatorで行うことで、難しく書くと「クラスの組み合わせに関する知識(情報)を局所化(決められた範囲に限ること)して」います。

Factory Method パターンの有効な条件

Factory Method パターンは次のような条件において有効に使うことができます。

・注意として、クラスが作成しなければならないオブジェクトのクラスを予測することはできません。

・クラスが作成するオブジェクトをサブクラスに指定させたいとき。

・複数のサブクラスのうちの1つのサブクラスに─役割を正常に実行する─責任をクラスが委譲させたときに、「どのサブクラスに責任を委譲した」のか、という"知識"を局所化(決められた範囲に限ること)したいとき。


今回は Factory Method パターンの構造を考えました。今回自分にとって意外で重要な気づきとしてはFactory Methodというのが「工場の製法」ということでクラスの特徴ではなく内部で共有される仕組みもしくは工程・仕掛けであったことです。まだAbstract Factoryしか紐解いていなかったこともあり、勝手にクラスの特徴だと思い込んでいました。メソッドをクラス間で効率よく使う方法だったというのが正体のように感じます。

加えてManipulatorに関してですが多分あっていないような気がしてなりません。しかし、このfactroy Methodは

普通template method (Template Method パターンを参照)であるanOperationから呼ばれる。

引用先URL:https://ja.wikipedia.org/wiki/Factory_Method_パターン

とあるように別のパターンでも登場するようです。

なのでこれから他のパターンの理解を進めていく中でもう一度 Factory Method パターンを考えられたらと思います。

この記事が参加している募集

この記事が気に入ったらサポートをしてみませんか?