「ファクトリーメソッドはテンプレートメソッドの特殊化」です。どうやって?


10

2つの間の類似点と相違点:

テンプレートメソッド

  • 継承に依存します。
  • アルゴリズムのステップを定義し、それらを実装するタスクをサブクラスに任せます。

ファクトリーメソッド

  • 継承に依存します。
  • スーパークラスは、オブジェクトを作成するためのインターフェースを定義します。サブクラスは、インスタンス化する具象クラスを決定します。

2つ並べて:

ここに画像の説明を入力してください

「ファクトリーメソッドはテンプレートメソッドの特殊化」というフレーズの意味がわかりません(Head First Design Patternsブックにあります)。ではBeverage、私たちの方法持ってprepareいるfinalと一連の手順を定義します。にPizzaStoreあるメソッドがありabstract、サブクラスがそれを再定義します。後者は前者を特化したものですか?


5
パターンポリスからのこの投稿には多くの反対票が表示されます。その理由は本当にありません。これで、このフレーズはおそらく不適切な言葉であると言う人が3人います。この投稿の読者への注意:本やオンラインで読んだすべてを信じてはいけません。
ロバートハーベイ

回答:


6

ではBeverage、私たちは(「テンプレート」)法持つprepareようないくつかの抽象メソッドを呼び出しますboilWaterbrewサブクラス内で実装されているなど。テンプレートメソッドを基本クラスに配置することは、基本的にパターンではなく、抽象メソッドがパブリックであると想定して、他の場所でも可能です。しかし、本質的には、オーバーライドする必要があり、「アルゴリズムテンプレート」のギャップを埋める抽象メソッドがあるということです。

ファクトリーメソッドは、抽象メソッドが上書きされるクラスにも関係します。コアポイントは、そのメソッドの呼び出し元が、作成されたオブジェクトの正確なタイプを知る必要がないことです。PizzaStoreでは、抽象メソッドcreatePizzaはどこかから呼び出されなければならないことに注意してください-メソッドと言いましょうcreateLotsOfPizza

これにより、後者がテンプレート方式になり、「ピザを作成するアルゴリズム」の特定のステップは、埋められるギャップになります。現在、「ファクトリメソッドパターン」は「テンプレートメソッド」パターンの特殊なケースであると言って、それはおそらく言葉の不正確な使い方です。特に「ファクトリメソッド」は「テンプレートメソッド」ではありませんが、テンプレートメソッドから呼び出される場合があります。より正確に言うと、

「ファクトリメソッドパターンは通常、テンプレートメソッドパターンの特殊なケースと組み合わせて使用​​されます。」

その本の著者が表現したかったのはそれだと思います。


2

「ファクトリーメソッドはテンプレートメソッドの特殊化」であると私は思います。テンプレートメソッドのパターンはファクトリーメソッドのパターンのバリエーションに過ぎないと言う方がより正確だと思います。

さらに、テンプレートメソッドのパターンは、継承とメソッドのオーバーライドによって自然に発生するので、実際には(Gang of Fourの意味で)まったくパターンではないと主張します。上の図のテンプレートパターンの図では、子孫クラスが独自の動作で基本クラスのメソッドをオーバーライドしているだけであることがわかります。

全体として、ソフトウェアパターン(ギャングオブフォーバラエティの)は、プログラミング言語の欠陥の回避策に過ぎず、テンプレートパターンは、オブジェクト指向言語がすでにネイティブで利用できる機能を再表現するだけです。


テンプレートメソッドをデザインパターンにしないデザインパターンの定義を使用している場合、その定義は間違っていると思います。デザインパターンは、コードのさまざまな部分間の関係を伝える抽象的なアイデアであり、実装されている言語とは関係ありません。デザインパターンは実装の詳細ではなく、高レベルで使用できる記述ですシステムの一部に関して行われた設計決定を伝えるため。
ジュール

より具体的には、テンプレートメソッドは、特定の状況で役立つ継承使用する特定の方法ですが、同じ目的を達成する他の方法があるため、これは明らかに設計上の決定です(たとえば、集計を使用して同じ効果を達成できます。その場合、それはおそらく戦略パターンのインスタンスと見なされます)。決定が下されていることを考えると、その決定について話すことができるように名前は重要であり、そのような名前がデザインパターンであることを示します。
ジュール

1

この特徴付けでは、ヘッドファーストは単に間違っていると思います。

ウィキペディアでは、テンプレートメソッドを次のように定義しています。

ソフトウェアエンジニアリングでは、テンプレートメソッドパターンは動作のアルゴリズムのプログラムスケルトンを定義する動作設計パターンであり、サブクラスにいくつかのステップを延期します。

(それはGoFを参照しています。)

また、ファクトリーメソッドは次のように定義されます。

クラスベースのプログラミングでは、ファクトリメソッドパターンは、作成されるオブジェクトの正確なクラスを指定せずに、ファクトリメソッドを使用してオブジェクトの作成の問題に対処する作成パターンです。

C ++では継承が両方の重要な部分であることを除いて、2つの間に重複はありません。ただし、実装の継承(extendsJava)とインターフェースの実装(Java)を区別する言語でimplementsは、インターフェースの実装でファクトリメソッドは十分ですが、テンプレートメソッドでは十分でないため、この共通性さえ存在しません。また、C ++では、前者には純粋な実装継承(インターフェース継承なし、つまりプライベート継承またはCRTPなし)を使用できますが、後者には使用できません。

それとは別に?1つは行動パターン、もう1つは創造パターンです。1つは操作の概要を説明するもので、一部の重要な部分は省略して、特殊なサブクラスで埋めます。もう1つは非常に単純なコントラクトを指定し、実装全体を具体的なインスタンスに任せます。それらは完全に異なります。

私の意見では、引用された行は単に間違っています。これは本の明白なエラーであるか、または(可能性は低いですが)コンテキスト外であり、異なる解釈が必要です。


この発言は単純な「間違った」ものではないと思います。それは単なるずさんな言葉の使い方です。私の編集を参照してください。
Doc Brown
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.