Builder デザイン パターンと Factory デザイン パターンの違いは何ですか?
どちらがより有利で、その理由は?
これらのパターンをテストして比較/対比したい場合、調査結果をグラフとして表すにはどうすればよいですか?
Builder デザイン パターンと Factory デザイン パターンの違いは何ですか?
どちらがより有利で、その理由は?
これらのパターンをテストして比較/対比したい場合、調査結果をグラフとして表すにはどうすればよいですか?
設計パターンでは、通常、すべてのケースで機能する「より有利な」ソリューションはありません。何を実装する必要があるかによって異なります。
ウィキペディアから:
- Builder は、複雑なオブジェクトを段階的に構築することに重点を置いています。Abstract Factory は、製品オブジェクトのファミリ (単純または複雑) を強調します。Builder は最終ステップとして製品を返しますが、Abstract Factory に関する限り、製品はすぐに返されます。
- Builder は、多くの場合、コンポジットを構築します。
- 多くの場合、設計は Factory Method (より単純で、カスタマイズ可能で、サブクラスが急増) を使用して開始され、設計者がより柔軟性が必要な場所を発見するにつれて、Abstract Factory、Prototype、または Builder (より柔軟でより複雑) に進化します。
- 作成パターンが補完的な場合もあります。Builder は他のパターンの 1 つを使用して、ビルドされるコンポーネントを実装できます。抽象ファクトリ、ビルダー、およびプロトタイプは、実装でシングルトンを使用できます。
ファクトリ デザイン パターンの Wikipedia エントリ: http://en.wikipedia.org/wiki/Factory_method_pattern
ビルダー デザイン パターンのウィキペディア エントリ: http://en.wikipedia.org/wiki/Builder_pattern
ファクトリは、コンストラクタ (おそらく別のクラスのコンストラクタ) の単なるラッパー関数です。主な違いは、ファクトリ メソッド パターンでは、オブジェクト全体を 1 回のメソッド呼び出しで構築し、すべてのパラメーターを 1 行で渡す必要があることです。最終的なオブジェクトが返されます。
一方、ビルダー パターンは、本質的に、コンストラクター呼び出しに渡す可能性のあるすべてのパラメーターのラッパー オブジェクトです。これにより、セッター メソッドを使用してパラメーター リストをゆっくりと構築できます。ビルダー クラスの 1 つの追加メソッドは build() メソッドです。このメソッドは、単にビルダー オブジェクトを目的のコンストラクターに渡し、結果を返します。
Java のような静的言語では、パラメーターのすべての可能な組み合わせに対してテレスコピック コンストラクターを使用する必要がなくなるため、(潜在的にオプションの) パラメーターが多数ある場合、これはより重要になります。また、ビルダーを使用すると、setter メソッドを使用して、コンストラクターが呼び出された後に直接変更できない読み取り専用またはプライベート フィールドを定義できます。
基本的な工場の例
// Factory
static class FruitFactory {
static Fruit create(name, color, firmness) {
// Additional logic
return new Fruit(name, color, firmness);
}
}
// Usage
Fruit fruit = FruitFactory.create("apple", "red", "crunchy");
基本ビルダーの例
// Builder
class FruitBuilder {
String name, color, firmness;
FruitBuilder setName(name) { this.name = name; return this; }
FruitBuilder setColor(color) { this.color = color; return this; }
FruitBuilder setFirmness(firmness) { this.firmness = firmness; return this; }
Fruit build() {
return new Fruit(this); // Pass in the builder
}
}
// Usage
Fruit fruit = new FruitBuilder()
.setName("apple")
.setColor("red")
.setFirmness("crunchy")
.build();
次の 2 つのウィキペディア ページのコード サンプルを比較する価値があるかもしれません。
http://en.wikipedia.org/wiki/Factory_method_pattern
http://en.wikipedia.org/wiki/Builder_pattern
Factory パターンは、ほぼ Builder パターンの単純化されたバージョンと見なすことができます。
ファクトリパターンでは、ファクトリは必要に応じてオブジェクトのさまざまなサブタイプの作成を担当します。
ファクトリ メソッドのユーザーは、そのオブジェクトの正確なサブタイプを知る必要はありません。ファクトリ メソッドの例として、または型指定されたオブジェクトcreateCar
が返されることがあります。Ford
Honda
Builderパターンでは、さまざまなサブタイプもビルダー メソッドによって作成されますが、オブジェクトの構成は同じサブクラス内で異なる場合があります。
車の例を続けると、 4 気筒エンジンの 型オブジェクト、または 6 気筒エンジンの 型オブジェクトcreateCar
を作成するビルダー メソッドがあるとします。ビルダー パターンは、このより細かい粒度を可能にします。Honda
Honda
Builder パターンとFactory メソッド パターンの両方の図は、Wikipedia で入手できます。
ビルダー デザイン パターンは、特定のタイプの別のオブジェクトをいくつかの手順で作成する方法を知っているオブジェクトを記述します。各中間ステップでターゲット項目に必要な状態を保持します。StringBuilder が最終的な文字列を生成するために何をするか考えてみてください。
ファクトリ デザイン パターンは、特定のタイプが特定のパラメーターに基づいて選択される、1 つのステップでいくつかの異なるが関連する種類のオブジェクトを作成する方法を知っているオブジェクトを記述します。シリアライザーを作成すると、目的の in オブジェクトがすべて 1 回のロード呼び出しで構築されるシリアライゼーション システムについて考えてみてください。
複雑なオブジェクトを段階的に構築する : ビルダー パターン
単純なオブジェクトは、単一のメソッドを使用して作成されます: ファクトリ メソッド パターン
複数のファクトリ メソッドを使用してオブジェクトを作成する : 抽象ファクトリ パターン
どちらも Object を作成するための Creational パターンです。
1) ファクトリ パターン - 1 つのスーパー クラスと N 個のサブ クラスがあるとします。作成されるオブジェクトは、渡されるパラメーター/値によって異なります。
2) ビルダー パターン - 複雑なオブジェクトを作成します。
Ex: Make a Loan Object. Loan could be house loan, car loan ,
education loan ..etc. Each loan will have different interest rate, amount ,
duration ...etc. Finally a complex object created through step by step process.
私が理解できた Builder と factory の顕著な違いの 1 つは、次のとおりです。
私たちは車を持っているとしましょう
class Car
{
bool HasGPS;
bool IsCityCar;
bool IsSportsCar;
int Cylenders;
int Seats;
public:
void Car(bool hasGPs=false,bool IsCityCar=false,bool IsSportsCar=false, int Cylender=2, int Seats=4);
};
上記のインターフェイスでは、次の方法で車を取得できます。
int main()
{
BadCar = new Car(false,false,true,4,4);
}
しかし、座席の作成中に何らかの例外が発生した場合はどうなりますか??? あなたはまったくオブジェクトを取得しません // しかし
次のような実装があるとします
class Car
{
bool mHasGPS;
bool mIsCityCar;
bool mIsSportsCar;
int mCylenders;
int mSeats;
public:
void Car() : mHasGPs(false), mIsCityCar(false), mIsSportsCar(false), mCylender(2), mSeats(4) {}
void SetGPS(bool hasGPs=false) {mHasGPs = hasGPs;}
void SetCity(bool CityCar) {mIsCityCar = CityCar;}
void SetSports(bool SportsCar) {mIsSportsCar = SportsCar;}
void SetCylender(int Cylender) {mCylenders = Cylender;}
void SetSeats(int seat) {mSeats = seat;}
};
class CarBuilder
{
Car* mCar;
public:
CarBuilder():mCar(NULL) { mCar* = new Car(); }
~CarBuilder() { if(mCar) { delete mCar; }
Car* GetCar() { return mCar; mCar=new Car(); }
CarBuilder* SetSeats(int n) { mCar->SetSeats(n); return this; }
CarBuilder* SetCylender(int n) { mCar->SetCylender(n); return this; }
CarBuilder* SetSports(bool val) { mCar->SetSports(val); return this; }
CarBuilder* SetCity(bool val) { mCar->SetCity(val); return this; }
CarBuilder* SetGPS(bool val) { mCar->SetGPS(val); return this; }
}
今、あなたはこのように作成することができます
int main()
{
CarBuilder* bp =new CarBuilder;
Car* NewCar = bp->SetSeats(4)->SetSports(4)->SetCity(ture)->SetGPS(false)->SetSports(true)->GetCar();
bp->SetSeats(2);
bp->SetSports(4);
bp->SetCity(ture);
bp->SetSports(true)
Car* Car_II= bp->GetCar();
}
ここで 2 番目のケースでは、1 つの操作が失敗しても Car を取得できます。
その車は後で完全に機能しないかもしれませんが、あなたはオブジェクトを持っているでしょう.
Factory Method は Car を 1 回の呼び出しで提供するのに対し、Builder は 1 つずつビルドするためです。
ただし、どちらを選択するかは設計者のニーズによって異なります。
BuilderとAbstract Factoryは、異なる目的を意味しています。適切なユース ケースに応じて、適切なデザイン パターンを選択する必要があります。
ビルダーの顕著な特徴:
工場(単純な工場) の顕著な特徴:
多くの場合、設計はFactory Method (より単純でカスタマイズ可能で、サブクラスが急増) を使用して開始され、 Abstract Factory、Prototype、またはBuilder (より柔軟でより複雑)に進化します。
関連する投稿を見てください:
デザイン パターン: ファクトリ vs ファクトリ メソッド vs 抽象ファクトリ
詳細については、以下の記事を参照してください。
Factory と Builder のパターンの使用法とその違いは、同じコード ベースで作業し、要件を変更することで、特定の期間でより簡単に理解/明確化できると思います。
私の経験から、通常は、主に比較的複雑な初期化ロジックを隠すために、いくつかの静的クリエーター メソッドを含む Factory パターンから始めます。オブジェクト階層がより複雑になるにつれて (または、より多くの型やパラメーターを追加するにつれて)、おそらくより多くのパラメーターがメソッドに入力されることになり、Factory モジュールを再コンパイルする必要があることは言うまでもありません。これらすべてのものは、作成者メソッドの複雑さを増し、可読性を低下させ、作成モジュールをより脆弱にします。
このポイントは、移行/拡張ポイントになる可能性があります。そうすることで、構築パラメーターの周りにラッパーモジュールを作成し、実際の作成ロジックに触れることなく、抽象化 (おそらく) と実装を追加することで、新しい (類似の) オブジェクトを表すことができます。したがって、複雑なロジックが「少なく」なりました。
率直に言って、「1 つのステップまたは複数のステップで作成されたオブジェクトを持つことの違い」のようなものを参照するだけでは、それらを区別するのに十分ではありませんでした。今は何のメリットもありません。そこで、最終的に考えたのがこれです。
どちらも非常によく似ていますが、オブジェクト作成用のパラメーターが多数あり、そのうちのいくつかはオプションで、いくつかのデフォルト値がある場合は、Builder パターンを使用してください。
ビルド パターンは、オブジェクト作成の複雑さ を強調します (「ステップ」によって解決されます)。
抽象パターンは、(複数だが関連する) オブジェクトの「抽象化」の「ちょうど」を強調します。
私見では
Builder は、ある種のより複雑な Factory です。
ただし、ビルダーでは、最終的で有効なオブジェクトを構築するために必要な別の factory を使用してオブジェクトをインスタンス化できます。
したがって、複雑さによる「創造的パターン」の進化について話すと、次のように考えることができます。
Dependency Injection Container -> Service Locator -> Builder -> Factory
私の意見では、ビルダーパターンは、他のオブジェクトの束からオブジェクトを作成したい場合に使用され、パーツの作成は、作成するオブジェクトとは独立している必要があります。パーツの作成をクライアントから隠して、ビルダーとクライアントを独立させるのに役立ちます。複雑なオブジェクトの作成に使用されます (複雑なプロパティで構成されるオブジェクト)
ファクトリ パターンは、共通のファミリのオブジェクトを作成することを指定し、それを一度に生成することを指定します。より単純なオブジェクトに使用されます。
違いは明らかですビルダーパターンでは、ビルダーは特定のタイプのオブジェクトを作成します。どのビルダーがビルドする必要があるかを指定する必要があります。factory pattern では、抽象クラスを使用して、特定のオブジェクトを直接構築しています。
ここでビルダー クラスは、メイン クラスと特定の型クラスの間のメディエーターとして機能します。さらなる抽象化。
ビルダーと抽象ファクトリー
Builder デザイン パターンは、Abstract Factory パターンにある程度似ています。そのため、どちらを使用するかによって状況を区別できることが重要です。抽象ファクトリの場合、クライアントはファクトリのメソッドを使用して独自のオブジェクトを作成します。Builder の場合、オブジェクトの作成方法を Builder クラスに指示してから要求しますが、クラスの組み立て方は Builder クラス次第であり、この点で 2 つのパターンの違いが生じます。
製品共通インターフェース
実際には、コンクリートビルダーによって作成された製品は構造が大きく異なるため、異なる製品を共通の親クラスから派生させる理由がない場合。これはまた、Builder パターンを、共通の型から派生したオブジェクトを作成する Abstract Factory パターンと区別します。
多くの設計は、Factory Method (複雑ではなく、サブクラスを介してよりカスタマイズ可能) を使用することから始まり、 Abstract Factory、Prototype、またはBuilder (より柔軟ですが、より複雑) に向かって進化します。
Builderは、複雑なオブジェクトを段階的に構築することに重点を置いています。
それを実装する:
Abstract Factoryは、関連するオブジェクトのファミリの作成を専門としています。Abstract Factoryは製品をすぐに返しますが、Builder は製品を取得する前にいくつかの追加の構築ステップを実行できます。
Bridgeと一緒にAbstract Factoryを使用できます。この組み合わせは、Bridge によって定義された一部の抽象化が特定の実装でのみ機能する場合に役立ちます。この場合、Abstract Factory はこれらの関係をカプセル化し、複雑さをクライアント コードから隠すことができます。
ファクトリ パターンでは一度に一度にオブジェクトを作成できますが、ビルダー パターンではオブジェクトの作成プロセスを中断できます。このようにして、オブジェクトの作成中にさまざまな機能を追加できます。