私は現在、デザインパターンについて学んでいます。 Factory Methodパターンについて学びました。
このパターンは、オブジェクトを作成するファクトリを実装するために、これらのオブジェクトを必要とするクラスをサブクラス化し、サブクラスにオブジェクトを作成させる必要があることを意味します。このように、スーパークラスは、サブクラスが生成する具体的な実装ではなく、より抽象的な参照でのみ機能し、疎結合の設計を作成します。
これは通常、スーパークラスがabstract
になることを意味します。これは、createObject()
メソッドがabstract
でなければならないため、ファクトリメソッドを含むサブクラスがこのメソッドを実装する必要があるためです。
他のファクトリパターンと同様に、このパターンは具象オブジェクトの作成をカプセル化し、クライアントがより高いレベルの抽象化で作業できるようにします。しかし、この特定のパターンは継承に基づいています。
私が理解していないことは-なぜ誰もがファクトリを必要とするクラスをサブクラス化してそれを作るというすべての問題を経験するでしょうabstract
? 構成は、この目的のために非常に優れています
抽象クラスまたはFactory
と呼ばれるインターフェイスを作成する方がはるかに理にかなっています。1つのメソッドを宣言します:createObject()
。我々は、さまざまな目的で具体的な実装を作成します(WeaponFactory
、TitleFactory
..)次に、クライアントにFactory
メンバーインスタンスfactory
を与えます。この参照は具体的に設定されますFactory
は実行時に必要であり、クライアントは必要に応じてfactory
のcreateObject()
を使用できます(具体的な実装を知らなくてもfactory
が保持しています)。
疎結合の方法でファクトリを使用できるようにするためだけに、クラスをサブクラス化して抽象化するという問題を経験する理由がわかりません。
私が説明したシンプルなコンポジションベースのデザインは、どんな面でも優れていると思います。
同意しますか?なぜ誰かが私が説明したファクトリーメソッドパターンを使うのか説明してくれませんか?
Design Patterns ブックはdescriptiveであり、prescriptive;ではありません。 GoFが実際に観察したパターンを説明しています。問題を解決するパターン。
一部の問題は、複数の方法で解決できます。
あなたが説明する代替案も私の好ましいアプローチですが、それは本にも説明されています: Abstract Factory と Strategy パターンの組み合わせです。抽象ファクトリを戦略として使用します。
疎結合の方法でファクトリを使用できるようにするためだけに、クラスをサブクラス化して抽象化するという問題を経験する理由がわかりません。
Abstract FactoryとStrategyを組み合わせるのとまったく同じ理由で。ただし、bestソリューションは、一部は言語によって異なります。
たとえば、Eiffelでプログラミングしている場合、Eiffelには複数の継承がありますが(IIRC)インターフェースがないため、ファクトリメソッドの方がおそらく簡単でしょう。
また、その場で派生値を作成できる言語(JavaまたはF#など)を使用している場合、ファクトリーメソッドは、実際には抽象ファクトリー/戦略コンボよりも簡単かもしれません。
一般的に、私はその構成が継承よりも優れていることに同意します。新しい抽象レベルで言語を構築する最初の試みがおそらくあるため、GOFデザインパターンは素晴らしいです。プログラムレベルではなくデザインレベルで、これは素晴らしいですが、いくつかの具体的なパターンはおそらく時代遅れであるか、あなたの具体的な状況、技術または好みに適応するように改善することができます。パターンの研究は良いことであり、いくつかの良いOOトリックとテクニックを教えることができますが、「本による」パターンの適用は決して良いアイデアではありません。IMMOです。
とにかく、私はあなたのデザインの問題、少なくとも静的型付き言語の問題、WeaponFactoryの戻りの武器とtitleFactoryの戻りのタイトルを私は思います、 "createObject"の戻りの型は異なり、この戻りの型は署名の署名の一部です方法。しかし、もちろん合成とDIを使用すれば、ファクトリーメソッドが達成しようとしているのと同じ目標を達成できます。例えば:
Client clientWithRealWeapon = new Client(new RealWeaponsFactory());
Client clientWithMocksWeapon = new Client(new MockWeaponsFactory());
構成とDIを備えたソリューションです。武器を作成するメソッドをオーバーライドするClientWithRealWeaponsとClientWithMocksWeaponsの2つのサブクラスを作成することで同じことができます。
私はあなたが問題を間違った方法で見ていると思います。いくつかのサブクラスの1つを作成する必要がある場合は、問題を解決するために説明したように、Factoryメソッドを使用する必要があります。
たとえば、コードの大部分を同じにする必要があるが、細部のみが異なるシステムがある場合、サブクラス化はそれ自体で意味があり、それを実行してから、次のようなファクトリを作成します。それぞれが必要とするルールに基づいて正しいサブクラスを追い出すことができます。また、サブクラスがすでに使用されているレガシーシステムがあり、その規模に応じて、オブジェクトの作成に役立つファクトリを追加したい場合があります。
Entityシステムのようなものを使用していて、Productオブジェクトのサブクラスが必要ない場合は、作成しないでください。ただし、単一のクラスが少なくともインターフェイスを実装していることを確認する必要がある場合があります。これは、ときどき、完全に無関係な実装を使用する必要があるためです。