web-dev-qa-db-ja.com

抽象ファクトリ:クライアントクラスはファクトリとの集約を持つことができますか?

最新のプログラミング言語を使用していくつかの抽象ファクトリの例を検索した後、抽象の概念UMLスキーマのsensu latoについて、具体的にはClient(Application(Application )クラスとその関係

ウィキペディアの例では、クライアントコードはファクトリーおよび各(ファミリーの)製品と関係があります。

enter image description here

一方、リファクタリングの達人ではクライアントコードにはFactoryを使用した集約があります

enter image description here

この最後の1つも「GOF」抽象ファクトリーと見なすことができますか?

もしそうなら、それは図を単純化し、具体的なファミリの使用を暗黙的で明示的ではないようにする別の方法にのみでしょうか?

3
celsowm

それは同じパターンであり、2つの図は実質的に同じです。パターンが実際に使用される方法の詳細の一部がややあいまいになっているだけであり、これにより、表面的に見た目が異なります。

破線の矢印は一般化された依存関係を表しています。つまり、あるタイプが別のタイプに依存していることを意味しますが、必ずしもインスタンスへの直接参照を保持しているとは限りません(たとえば、 typeは、関数のパラメーターとして、または関数の戻り型として表示されます)。

最初の図では、クライアントコード依存関係がない(知識がない)コンクリート製品またはコンクリートファクトリ-クライアントからのすべての矢印は、抽象的なインターフェイスのみを指しています。つまり、すべてのクライアントコードは、これらの抽象インターフェースに関してのみ記述されています。

これは、クライアントがコンストラクターを介して依存関係としてファクトリーを受け取ることを除いて、2番目の図に示されている状況とまったく同じです(ただし、抽象インターフェースを介して入力されます)。それが集約であるという事実は、全体的なパターンに対して何の意味も持たない詳細(実装の選択)です-重要なこと、そしてそれを最初の図と同等にするのは、(1)factoryのタイプです。フィールドはAbstractFactory(具体的なファクトリではありません)であり、(2)AbstarctFactoryのプロデューサーメソッドの戻り値の型はすべて抽象的な製品です。クライアントがこれらのタイプを使用するという事実は、最初の図の破線の矢印に対応しています。

たとえば、someOperation()には次の行が含まれています。

_ProductA pa = factory.createProductA();  // Note that ProductA is the abstract type
// presumably, the remainder of the code then does something with pa
_

つまり、ClientsomeOperation()を定義)はProductAに依存します。この依存関係は、最初の図では、ClientからAbstractProductAへの破線で表されています。この表現では正確に表示されないだけですhowこの依存関係が発生し、そこにあるだけです。 2番目の図では、この依存関係は暗黙的であり、示されている他の要素から推測できます。

これらの図に示されていないことの1つは、実際に選択されるコンクリートファクトリーの方法です。これを行ういくつかのthirdコンポーネントがあります-これは、多くの場合、Main()メソッドのようなある種のエントリポイント、モジュールへのルート、またはグループへのルートです。コラボレーションするオブジェクトの。つまり、使用したい具体的な製品がわかっている別の場所で発生します。

コンクリート工場自体は、対応するコンクリート製品に依存しているため、これらを構成する必要はありません(どのコンクリート製品を使用するかは、コンクリート工場の選択によって決まります)。選択が行われると、ファクトリへの抽象的な参照が何らかの方法でクライアントに渡されます。これにより、クライアントは具体的な製品から切り離されたままにすることができます。

したがって、欠けている部分は次のようになります。

_static public void Main(string[] args)
{
    // Any mention of anything concrete is confined to this line 
    // (and within the ConcreteFactory1 itself)
    AbstractFactory factory = new ConcreteFactory1();

    Client client = new Client(factory);
    client.SomeOperation();
}
_

選択は、ここに示すように、または構成ファイルのエントリに基づいて、またはプリプロセッサディレクティブを介して実行するか、何らかの方法で動的に決定するなど、ハードコード化できます。ファクトリインスタンスは、「手動」でクライアントに渡すことができます。 IoCコンテナーによって作成、注入、および管理できます。

3

2番目の図は、抽象的なファクトリを表す場合があります。ただし、これをこのパターンの参照図として見ることはできません。

  • GoFによると、AFクライアントはファクトリを使用します。それ以上は教えません。 2番目の図では、クライアントがファクトリに関連付けられています。これにより、その使用が可能になりますが(GoFに準拠)、はるかに強力です(したがって、すべてのGoFファクトリーは2番目の図と一致しません。クライアントは、メソッドパラメーターとして提供されるAFを集約なしで十分に使用できます)。
  • GoFによれば、クライアントは具体的な製品ではなく抽象的な製品を知っています。これは2番目のスキーマでは指定されていません。簡単に推測できますが、図では具体的に結合されたクライアントを実装することもできます(Webサイトのテキストとコードのサンプルで、この重要なポイントが明確になることを願っています)。
  • ちなみに、集計の正確なセマンティクスは、UML仕様では指定されていません。したがって、非集計の関連付けと比較して、ここでは追加情報は提供されません。
3
Christophe