23

この質問があちこちで何度か出てくるのを見てきましたが、満足のいく答えは見つかりませんでした。

ウィキペディアから:

Builder は、複雑なオブジェクトを段階的に構築することに重点を置いています。Abstract Factory は、製品オブジェクトのファミリ (単純または複雑) を強調します。Builder は最終ステップとして製品を返しますが、Abstract Factory に関する限り、製品はすぐに返されます。

しかし、クライアントにとっては同じことではないでしょうか。オブジェクトが構築されると完全なオブジェクトを取得するため、追加機能はありません。

私が見る唯一の方法は、ビルダーの実装のための構造を強制するために、コンストラクターコードを段階的に編成する方法です。これは素晴らしいことですが、抽象的な工場からの大きな一歩ではありません。


ウィキペディアからのこの次のビットは、私の要点を理解するための良い参考資料です。

多くの場合、設計は Factory Method (より単純で、カスタマイズ可能で、サブクラスが急増) を使用して開始され、設計者がより柔軟性が必要な場所を発見するにつれて、Abstract Factory、Prototype、または Builder (より柔軟でより複雑) に進化します。

その場合、Abstract Factory から Builder に変更する場合、システムにどのような複雑さを導入する必要がありますか?

私の要点は、Abstract Factory では不十分であり、代わりに Builder が必要になることが明らかな場所を見つけて例を挙げられないということです。

4

10 に答える 10

13

AbstractFactory は、関連製品のファミリ用です。Builder は 1 つの製品用です。

Builder は複雑な製品を段階的に構築するためのものであり、AbstractFactory は抽象的な方法で (つまり、いくつかの実装に対して 1 回) 複雑でない製品を構築するためのものです。


呼び出しコードに対する違いの意味の例:

  • AbstractFactory を使用するクライアント コードでは、メソッド呼び出しごとに 1 つのオブジェクトが構築されます。クライアントはそれらを一緒に組み立てる必要があります。一方、ビルダーはそれらを内部で組み立て、構築の最後のステップとして完全なオブジェクト グラフを提供します。

  • ビルダーを使用すると、クライアント コードのパラメーターを 1 つずつ渡してチェックすることができます。しかし、彼は 1 つのステップで最終製品をビルドする場合があります (たとえば、コンストラクターを呼び出して、一度にすべてのパラメーターを渡します。それ自体がビルドされた洗練されたものであっても)。したがって、ビルダーの製品は、不変オブジェクト (またはグラフ) になる可能性があります(これは、パフォーマンスとメモリの理由から、マルチスレッド環境では貴重です)。


このコメントに応じて更新:

リノ > それでも気になりますよね :)。つまり、複合オブジェクトを構築していて、ディレクターを外して、ビルダー メソッドを呼び出す責任をクライアントに渡せば、うまくいきます。そうして初めて、ビルダーは完璧にフィットするように見えます. でも、監督からすれば、たいしたことじゃないような……。

正確には、ビルダーにはディレクターがなく、各クライアントが特定のニーズに応じて複雑な製品を作成できるようにします。ディレクターの実装は再利用されないため、クライアントはディレクターです。

複雑な構築プロセスを数回再利用する必要がある場合は、これをカプセル化するメソッドを用意できます (このメソッドは「ディレクター」です)。

反対に、AbstractFactory の場合は通常、同じような製品を作成する再利用可能な Director が必要です(Factory 実装で提供されます)。

于 2009-12-22T15:07:34.427 に答える
7

ここにはすでにいくつかの非常に良い答えがあります。類推を提供しているだけです。

新しいオフィスに新しいデスクが必要だとします。「工場」に行き、選択を確認してから、棚の 1 つを選びます。それがあなたのニーズに合っているなら、素晴らしいです!

これで、非常に凝った形の壁を備えたより大きなオフィスができました。今、あなたのオフィスに合う形の天板を備えたデスクが必要です。残りの家具や新しいアーロンチェアに合うように、別の脚が必要です。

あなたは同じ工場に戻りますが、運が悪いです。あなたは、あなたが望むものをカスタム「構築」できる大工に行きます。仕様と要件を指定すると、「ビルダー」が特定の制限を教えてくれます。数回繰り返した後、完璧なデスクが完成しました。

わかりました、下手な話ですが、物事を明るくするだけです:P

于 2009-12-22T15:21:12.727 に答える
4

ビルダーが必要な 1 つの良い例は、コマンド ライン引数に基づいて何かを少しずつビルドする場合です。たとえば、次のようなメソッドを持つビルダーを考えてみましょう...

setName()
setType()
setOption()

ビルダーは、ディレクターが工場に具体的な製品を要求する抽象的な工場と組み合わせることもできます。繰り返しますが、これは引数リストをファクトリに渡すことによってファクトリ パターンだけで実行できますが、引数が代わりにサーバーまたはクライアントからのメッセージである場合はどうなるでしょうか。

場合によっては、あるパターンの美学が他のパターンの美学よりもうまく適合することがあります。

于 2009-12-22T15:16:07.980 に答える
2

Builder は、Template Method Pattern のような制御の反転です。コンクリート ビルダーのさまざまな機能は、プロセス内のカスタマイズ可能なステップです。抽象ファクトリは、出力がたまたま新しく構築されたオブジェクトである「単なる」ポリモーフィズムです。具体的なファクトリのさまざまな機能は、カスタマイズ可能なさまざまなプロセスであり、それぞれが異なるオブジェクトになると考えられます。

したがって、オブジェクトを構築するための共通の全体的な「プロット」が必要であるが、そのプロット内の個々の「シーン」が異なる場合は、ビルダーが必要です。異なる実装間で共通点がまったくない場合は、ファクトリが必要です。

Abstract Factory が Builder パターンのディレクタとして機能し、それぞれの具象ファクトリが異なる方法で物事を指示することで、両方を同時に使用できると思います。ただし、それはUML図の「ナプキン」制限を超えています;-)

于 2009-12-22T17:06:05.200 に答える
2

Builder は設定に役立ちます。Abstract Factory は、呼び出し元に実際の実装を気にさせたくない場合に便利です。2 つの異なる目的。

You could, in fact, mix the two patterns. For example Java's DocumentBuilderFactory is a classic abstract factory: if you read the docs, you'll see the process that it uses to pick an implementation. However, the DocumentBuilders that it produces can be configured afterward (although they don't follow the prototypical "builder" approach of having each configuration method return the object being configured).

于 2009-12-22T15:10:16.307 に答える
1

アナロジーを考えてみましょう。

あなたはファースト フード チェーンにいますが、実際に手に入れるファースト フードは非常に複雑です。複雑なだけでなく、特定の人だけが特定の種類の食べ物を注文することができます. 店長が 1 つのレジの後ろに 1 人を配置することにしたためです。でもよく見ると「抽象的」だから、実は高度なホログラムなんです。抽象的な注文係。ホログラムに話しかけて注文すると、ホログラム コンピューターはその注文を人間の注文担当者の脳に埋め込まれたインプラントに転送します (ポリモーフィズム)。インプラントは、実際のレジスターに合わせて人間を実際にパンチさせます。これらの「コンクリート」はほとんどありませんホログラムによって命令されているマインドコントロールされた人間。さて、本物の人間が注文にパンチを入れると、それは後ろのコンピューターに送られます。そこでは、製造中の食品の種類ごとに組み立てラインまたは「ビルダー」があります。注文は、人間とレジに基づいて、さまざまな種類の組み立てラインに送信されます。

つまり、ホログラムは抽象的な工場であり、レジスターにいるマインド コントロールされた人間は具体的な工場であり、組み立てラインはビルダーです。これは、ビルダー パターンで動作する抽象ファクトリのフローを実際に視覚化できる方法です。デザイン パターンがどのように異なるかを確認するために、デザイン パターンがどのように連携するかを確認するのが最善の場合もあります。

追加のクレジットを探している場合は、これをジェネリックで実装してみてください。思ったほど多くのコードは必要ありません。

于 2009-12-24T16:31:07.817 に答える
1

複数の子ファクトリを構築してさまざまなタイプのオブジェクトを作成する必要がある場合は、Abstract Factory を使用します。これらの子ファクトリはすべて、Abstract Factory を実装または拡張します。ビルドする必要があるオブジェクトのタイプが 1 つしかない場合は、ビルダーを使用します。

これが正しい使い方かどうかはわかりませんが、これは私が見た方法であり、過去に行った方法です。

于 2009-12-22T15:10:36.977 に答える
0

Builderパターンを使用するタイミングとその利点の詳細については、私の投稿で別の同様の質問を確認してください。

于 2009-12-23T18:43:07.503 に答える
0

良い答えです。私の理解が正しいことを発見したことを願って、私のものを追加したいと思います。

新しいオフィスがあり、新しいデスクのみが必要な場合は、ビルダーを使用します。机は常に机になりますが、机にはさまざまな構成があります。つまり、サイズ、形状、ハッチの存在、引き出しなどです。

新しいオフィスがあり、内部が完全にむき出しの場合は、さまざまなオブジェクトが必要になり、家具を作成するAbstract Factoryを使用し、そこからデスクが降りてきます。この場合、私たちが知っているDeskは「複雑な」オブジェクトであるため、Builderパターンを使用しますが、ここでは、DirectingAbstractFactoryの一部です。Abstract Factoryは、StraightFunkyLampFactoryクラスを介して、非常に特殊なランプ(StraightFunkyLamp)などの単純なオブジェクトも作成します。

于 2013-03-07T23:03:01.113 に答える
0

実際には、ビルダーが行っていたことを行うために、おそらく DI + IOC を使用するでしょう。ご参考までに。

于 2011-01-27T22:29:45.500 に答える