6

Factory パターンを使用していると思われる Java コードを扱っていましたが、そのパターンに完全には納得していません。

私のコードはこれを行います:

// the factory
class SomeFactoryImpl {
   Set<SomeClass> getSomeListOfObjects();
}

そして、コードのどこかに:

{ ...
    SomeFactory factory = new SomeFactoryImpl();
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

私が考えているポイントは、ファクトリ クラスに静的な create() メソッドがない場合、ファクトリをインスタンス化する必要があるということです。この IMO は、オブジェクト自体をインスタンス化するのと同じくらい複雑でなければなりません。

そのようなファクトリが生成されるオブジェクトのコレクションを返すことができるという議論は十分ではないと思います。ファクトリから実際にオブジェクトを作成する前にファクトリ インスタンスを作成する必要がある場合は、よりクリーンな回避策があると思います。

createメソッドはファクトリクラスのstaticメソッドの方がいい気がします。しかし、私の意見が完全に「正しい」わけではないことも確信しています。

SO コミュニティは、ファクトリ オブジェクトをインスタンス化する方が静的な作成メソッドを使用するよりも優れている例を示すことができますか?

また、これらのリンクと回答をリストした同様の質問への回答に出くわしました。そのため、FactoryMethodPatternFactoryMethod、およびCreationMethodの違いをコード例で明確に知る必要があります。

4

5 に答える 5

5

ファクトリのインスタンスを使用すると、依存性注入と組み合わせると真のメリットが得られます。

したがって、あなたの例では、代わりに:

{ ...
    SomeFactory factory = new SomeFactoryImpl();
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

次のようになります。

public ThisClass(SomeFactory someFactory) {
    this.factory = someFactory;
}   

じゃあ後で...

{ ...
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

いくつかのポイント:

  • この状況では、クラスは具体的なファクトリへの参照を持たず、SomeFactoryImpl について知る必要はなく、抽象化された SomeFactory についてのみ知っています。
  • この場合、渡されるファクトリ インスタンスは、静的ベースではなく、インスタンス ベースで構成できます。これは、(私の意見では) それを処理するより適切な方法である傾向があります。ファクトリ インスタンスを不変にすることができれば、マルチスレッドの心配を本当に減らすことができます。
  • インスタンスを提供するための静的呼び出しを持つことは、それほど優れているわけではありません。それを作成するクラスへの参照は、依然として具体的な実装の詳細です。それは単に上位にありますが、問題を解決するのに十分な高さになる可能性があります。

これはあなたの質問のサブセットにしか対応していないことを知っています...

于 2009-06-22T11:31:15.270 に答える
1

まず、ファクトリパターンの主な目的を忘れているので、私は4人組の本を開きました。

「オブジェクトを作成するためのインターフェースを定義しますが、インスタンス化するクラスをサブクラスに決定させます。ファクトリメソッドを使用すると、クラスはインスタンス化をサブクラスに延期できます。」

これは、実際にはインターフェイスを定義することを意味します。SomeFactoryImpl実際には、別の場所で定義されたインターフェイスを実装する必要があります。これは、インスタンス化する必要のあるオブジェクトが多数あるが、それらがどの種類のオブジェクトであるかを気にしたくない場合に便利です。たとえば、クライアントがシリアル化によってダウンロードするリモートスイングアプリケーションを開発するためにそれらを使用しました。クライアントVMに存在しなかったいくつかのクラスの定義。すべてのクラスは、特定のビューを持つJPanelのサブクラスを定義しましたが、クライアントに到達するときに、これらのクラスを知らずにインスタンス化する方法を見つける必要があったため、ファクトリパターンを使用してファクトリクラスを呼び出し、未知のオブジェクトをインスタンス化しました(私が定義したJPanelのサブクラスを拡張しています)。もう1つの例は、ニーズに合わせてケース固有のオブジェクトを生成することです。

ただし、静的メソッドを使用して特定の問題を解決することもできますが、大きなプロジェクトでアイテムを使用する部分からアイテムを生成する部分を分割することを検討してください。もちろん、クライアントパーツを開発しているのは、どのファクトリインターフェイスが使用されているかを知っている必要があり、他のパーツで定義されているすべてのオブジェクトを使用するには、これだけを知っている必要があります。

作成パターンは、標準の定義(メソッドの名前がクラスの名前と同じ)を使用せずにコンストラクターのカスタムバージョンを定義するためだけに使用される一種の「ファシリティ」パターンですが、特別なことではありません。オブジェクトをインスタンス化するための別の方法..作成パターンは、実際には特定の問題を解決しません(同じ数と種類の引数を持つコンストラクターを除く)。

于 2009-06-22T10:51:02.310 に答える
1

オブジェクト作成の静的メソッドが最も一般的なアプローチだと思いますが、最初にファクトリ インスタンスを作成することが理にかなっているユース ケースもいくつかあります。たとえば、レジ​​ストリと組み合わせたい場合 (複数のレジストリの共存を許可する必要がある場合)。

また、ファクトリが何らかの動的なコンテキスト情報 (データベース接続など) に依存している場合、私の意見では、ファクトリ インスタンスにこれを処理させる方が適切です。

于 2009-06-22T10:39:46.920 に答える
0

ファクトリ オブジェクトのインスタンスを作成する理由は次のとおりです。

  1. ファクトリを作成して構成し (青のウィジェットと赤のウィジェットを作成するなど)、必要に応じて青のウィジェットと赤のウィジェットを作成できるようにします。RedWidgetFactoryこれは,を持つこととは異なることに注意してくださいBlueWidgetFactory。構成は、作成されるオブジェクトのタイプに直交します
  2. これにより、システム全体で 1 つのファクトリ (静的メソッドを介してアクセス) を使用することで発生する可能性のあるスレッドの問題が軽減されます。これは少し防御的かもしれませんが、(特に大規模なシステムでは) 良い考え方だと思います。もちろん、オブジェクトがどのように作成されるかによって異なります (たとえば、ファクトリは共有される基本コンポーネントを作成します)。
于 2009-06-22T11:11:09.307 に答える
0

IMO、あなたが持っているコードはその使用が完全に最適ではない場合でも、確かに GoF Abstract Factoryパターンの適切な見本です。私の記憶が正しければ、GoF ブックはファクトリ (SomeFactory、SomeFactoryImpl) と製品 (SomeClass) の間の関係を説明していますが、ファクトリのインスタンス化の詳細はオープンのままです。

あなたが持っているものが、広く使用される予定のない内部 API である場合、あなたが持っているものでおそらく十分です。それ以外の場合は、次のことができます。

  1. 別のクラス (いわば「ファクトリ マネージャ」) に、パラメータ (JDBC の DriverManager など) またはその他のコンテキスト情報に基づいてファクトリの実装を選択させます。
  2. ある種の依存性注入フレームワークを使用します。

#1を使用する場合、私は通常、JDBCに従ってモデル化しようとします。ここで:

  • Driver抽象工場になります
  • ConnectionsなどStatementsは商品です
  • DriverManager(GoF ブックでは明示的に指定されていません) は、渡された JDBC URL に基づいてファクトリを選択するユーティリティ クラスです。

(この場合、ほとんどDriverManagerの場合と同様に、 メソッドを使用すると、 が先に進み、製品も作成しますgetConnection(...)。)

それをあなたの質問に結び付けるために、間違いなく呼び出してJDBCを使用できます

new OracleDriver().connect(...)

しかし、あなたが指摘したように、これは次善であり、抽象的なファクトリ パターンを使用する目的を幾分無効にします。

この問題は、ある日、そのパターンがファクトリの作成方法について実際に明示的に語っていないことに気付くまで、私を悩ませていました。

これがあなたの質問に答えることを願っています。

于 2009-06-22T11:11:42.470 に答える