Builder Design パターンと Factory Design パターンの違いは何ですか?
-
09-09-2019 - |
質問
Builder デザイン パターンと Factory デザイン パターンの違いは何ですか?
どちらが有利ですか?またその理由は何ですか?
これらのパターンをテストして比較/対照したい場合、調査結果をグラフとして表現するにはどうすればよいですか?
解決
デザインパターンが通常でない"より有利な"ソリューションすることができます。で必要なものするものをいいます。
Wikipediaから:
- ビルダを構築 複雑なオブジェクト。概要 工場重視の製品 オブジェクト(または簡たりすることができます。ビルダーを返します製品として最終 ステップがどの概要 工場では、製品が 直ちに返還していただきます。
- ビルダーがビルドを合成した。
- しばしば、デザイン開始を用いてファクトリメソッド以下に複雑に、より カスタマイズ,サブクラスは増殖) と進化に向けての抽象工場 試作品、またはビルダー(柔軟になり、 より複合体)としてのデザイナー 発見がより柔軟であ 必要です。
- 時creationalパターンを補完す:ビルダーご利用でき その他のパターンの実施 るコンポーネントを構築する。概要 工場-ビルダー製作、試作で 利用シングルトンを になります。
Wikipedia工場デザインパターン:http://en.wikipedia.org/wiki/Factory_method_pattern
Wikipediaのエントリビルダーデザインパターン:http://en.wikipedia.org/wiki/Builder_pattern
他のヒント
工場 単純にラッパー機能周辺コンストラクタ(おそらく一つになっています。-の重要な違いがあることでファクトリメソッドのパターンの全体オブジェクトの構築を単一のメソッドの呼び出しはすべてのパラメータを渡し、単一ます。最終オブジェクトが返されます。
ビルダのパターン, 一方、本質的にはラッパーオブジェクトの周りの全てのパラメータにするためにパスへのコンストラクタを呼び出し.ここで利用できる設定メソッドでゆっくりくために、自分たちのパラメータ一覧です。できるように、幾つかのメソッドをビルダークラスが構築()メソッドは、単純に過去においbuilderオブジェクトの任意のコンストラクタを返します。
静的言語のようなJava、この重要性が増すとき以上に、一握りの可能オプション)パラメータとしてされることを回避することができ、必要望遠コンストラクタが用可能なすべてのパラメータの組み合わせ.もbuilderで利用できる設定メソッドを定義する読み取りまたはprivateできない直接変更後のコンストラクタと呼ばれています。
基礎工場の例
// 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();
するのが良いでしょう比較するとコードのサンプルからこれら二つのwikipediaページ:
http://en.wikipedia.org/wiki/Factory_method_pattern
http://en.wikipedia.org/wiki/Builder_pattern
Factory パターンは、Builder パターンの簡略化されたバージョンとみなすことができます。
の中に 工場 パターンに応じて、ファクトリーはニーズに応じてオブジェクトのさまざまなサブタイプの作成を担当します。
ファクトリ メソッドのユーザーは、そのオブジェクトの正確なサブタイプを知る必要はありません。ファクトリメソッドの例 createCar
を返すかもしれない Ford
または Honda
型付きオブジェクト。
の中に ビルダー パターンでは、ビルダー メソッドによって異なるサブタイプも作成されますが、オブジェクトの構成は同じサブクラス内でも異なる場合があります。
車の例を続けるには、次のようにします。 createCar
を作成するビルダーメソッド Honda
4気筒エンジンを搭載したタイプのオブジェクト、または Honda
6 つのシリンダーを持つ型付きオブジェクト。ビルダー パターンでは、このより細かい粒度が可能になります。
両方の図 ビルダーパターン そしてその ファクトリメソッドパターン ウィキペディアで入手できます。
ビルダーデザインパターンはいくつかの段階で、特定の種類の別のオブジェクトを作る方法を知っているオブジェクトを記述します。これは、各中間段階での目標項目の必要な状態を保持しています。 StringBuilderのが最終的な文字列を生成するために経由するものを考えてみます。
工場デザインパターンは、特定の型が指定されたパラメータに基づいて選択される1つのステップでオブジェクトのいくつかの異なるが関連の種類を作成する方法を知っているオブジェクトを記述する。あなたのシリアライザを作成し、シリアル化システム、を考えると、それはすべて1回のロードの呼び出しでオブジェクト内の所望の構築ます。
構築の複雑なオブジェクト順:ビルダーパターン
単純なオブジェクトを使用して作成した単一の方法:ファクトリメソッドのパターン
作成のオブジェクトにより複数のファクトリメソッド:抽象パターン工場
両方のオブジェクトを作成するために、生成に関するパターンである。
1)工場出荷時のパターン - 想定、あなたは1つのスーパークラスとサブクラスのN番号を持っています。 オブジェクトが作成され、パラメータ/値が渡されたに依存します。
2)Builderパターン - 複合オブジェクトを作成する
。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パターン、どちらもあなたのためのオブジェクトを作成するので、両方は肉眼ではかなり似ているようです。
しかし、あなたは近い
を見てする必要がありますこの実際の例では、さらに2つの明確な違いを行います。
とし、あなたはファーストフードのレストランに行って、あなたはの食品を命じました。
1)どんな食べ物?
ピザ
2)どのようなトッピング?
トウガラシ、トマト、バーベキューチキン、NOの PINEAPPLE の
食品のように、異なる種類のFactoryパターンによって作られていますが、特定の食品の異なる変種(味が)ビルダーパターンによって作られています。
食品の異なる種類
ピザ、バーガー、パスタ
ピザのバリアント
のみチーズ、チーズ+トマト+トウガラシ、チーズ+トマト等
コードサンプル
あなたはここで、両方のパターンのサンプルコードの実装を見ることができます
Builderパターンの
ファクトリパターンの
第一般的なものに従って環境における議論:
本課題の設計に大きなソフトウェアシステムは、柔軟性を十分に変化します。このため、あるメトリクスのようにカップリングと結合.現システムに簡単に変更または拡張機能の必要がなく、アジア全体のシステムをゼロから立ち上げまでのデザイン原則のように固ます。した後、一部の開発者で認められていた場合に、原則ある類似のソリューションなどについても、同様の問題にその標準的なソリューションのデザインパターン
そのデザインパターン支援に従って一般のデザインの方針達成のための疎結合システムの高い結束という
質問に答え:
いの違いを二つのパターンを使い自分を何パターンのシステムをごる方法の自由度は飛躍的に向上します。各パターン独自の目的整理の間の依存関係の授業でございます。
の概要工場でのパターン: GoF:"提供インタフェース作成の家族関係には依存のオブジェを指定せずにその具体的な授業になる"
これはなぜですか?: 提供することによりこのようなインタフェースの呼び出しのコンストラクタのそれぞれの家族の商品に封入されていますのfactoryクラスです。ここでも通りにくい難所であったためにシステム全体がコンストラクタと呼びま変更することが可能なシステムを導入したことにより新工場のクラスです。場合は取引所の表現の場を通じて、交換することで全体の製品に触れることなく多数のコードです。
ビルダをインストールパターン: GoF:"別の複雑なオブジェクトからその表現をその構築過程を異なる表現に変換するものである。"
これはなぜですか?: ま封止工事の別のクラスと呼ばれる取締役(GoF).このディレクターを含むアルゴリズムの作成新しいインスタンスの例を構成する複雑な製品のその他の部分。を一体パーツの製品の使用ビルダを構築します。の交流によるビルダをインストールの取締役に、そのまま使うことができアルゴリズムの作成は、製品が変更に表現シートカバー単品パーツ(その表現までお問い合わせ下さい。延または変更すシステムの表現は、製品だけで導入することによって、現在新しいビルダークラスです。
などにより: の概要工場によりパターンの目的は交換のセットを使用した製品に使用されます。ビルダをインストールパターンの目的は封止に抽象的アルゴリズムの作品を再利用するために異なる表現の製品です。
私の意見できないというの概要工場でのパターンの兄ビルダをインストールパターンです。あり、両creationalパターンだけでなく、本意のパターンはまったく異なるのだという。
私が作ることができるビルダー&工場間の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);
}
しかし、いくつかの例外が席を作成中に何が起こるかあれば? YOUはATすべてのオブジェクトを取得することはできません// が、
あなたのような実装があるとし、次の
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();
}
ここでは後者の場合では、一つの操作が失敗した場合でも、あなたはまだ車になるだろう。
あなたがオブジェクトを持つことになり、その車が後に完璧に動作しないことができるが、ます。
ビルダーを1つずつ構築するのに対し、ファクトリメソッドは、単一の呼び出しであなたの車を与えるので。
が、それはのために行くするかを快くのニーズによって異なります。
+-------------------------------------------------------------------+---------------------------------------------------+
| Builder | Factory |
+-------------------------------------------------------------------+---------------------------------------------------+
| Return only single instance to handle complex object construction | Retrun various instances on multiple constructors |
| No interface required | Interface driven |
| Inner classes is involved (to avoid telescopic constructors) | Subclasses are involved |
+-------------------------------------------------------------------+---------------------------------------------------+
ナ
- 工場: を考えるレストランです。の創出"本日のお食事は工場でのパターンがをしないといけないと考えていキッチン"も本日のお食事、キッチン(工場)を決定しうオブジェクトの生成に基づき、隠れた基準とします。
- ビルダー: ビルダをインストール画面が表示されますの順にタッフを募集しています。この場合、ウェイタ語の料理長(ビルダー)"が必要なピザ;チーズを加えたまねぎ、ベーコンをもう!" これにより、ビルダーオの属性を生成したオブジェクトは、隠どのように設定します。
ビルダー や 工場概要 えたという。によって使いの場合、いかなければならない。デザインパターンです。
ビルダー 特徴:
- ビルダーパターンを複合オブジェクトを簡単なオブジェクトを使用した段階アプローチ
- ビルダクラスのビルドの最後のオブジェクト。このビルダーは独立したその他のオブジェクト
- 差し替え工法/概要工場ではこのシナリオ:多すぎるからクライアントプログラムのファクトリクラスでエラーが
- 一部のパラメータがオプションとは異なり、工場部隊を送りすべてのパラメータ
工場 (簡単な工場)特徴:
- Creationalパターン
- 継承
- 工場を返すファクトリメソッド(インタフェース)を返しますコンクリートオブジェクト
- でも代用できますので新しいコンクリートの物体とのインターフェイスとクライアント呼び出し側のときに意識すべてのコンクリート実装
- お客様は常にアクセスインターフェースのみを非表示にすることができオブジェクト作成の詳細に工場方法です。
しばしば、デザイン開始を用いて ファクトリメソッド 以下に複雑に、よりカスタマイズ,サブクラスは増殖や進化に向けて 工場概要, 試作, や ビルダー (柔軟に、より複雑な)
見て関連するポス:
されていることをご確認ください下記の記事の詳細:
概要工場-ビルダーパターンの両方Creationalパターンが異なる意図するだけでも構いません。
抽象パターン工場 を重視オブジェクト作成のための家族に関連オブジェクトが
- それぞれの家族のセットの派生クラス共通の基底クラス/インタフェース。
- 各オブジェクトは直ちに返還していただきますの結果としてます
ビルダーパターン を構築-運用に関する複雑なオブジェクト。で分離の表現から構築プロセスの複雑なオブジェクトよって発見されており、そのため建築工程に使用できる異なる表現に変換するものである。
- ビルダオブジェクトをカプセル化の構成の複雑なオブジェクトです。
- 取締役オブジェクトを知り尽くプロトコル用のビルダーの プロトコルを定義して論理的に必要なステップの構築の複雑なオブジェクトです。
複雑な工事の場合、オブジェクト構成の異なる他のオブジェクトが表す抽象化.
を考えるメニューにマクドナルドです。メニューを含むドリンク、主と。によって子孫に個別に抽象化され、作成したメニューも表現。
- 例:コーラ、Mac、フライドポテト
- 例:スプライト、ナゲット巻き揚げ
が持っていた自分としては、二つのインスタンスのメニューの異なる表現に変換するものである。工事の順番に変更はありません。自分の好きな名前を付けてメニューのドリンクを飲み、主と。
用ビルダをインストールパターンは、別のアルゴリズムの作成は複雑なオブジェクトからの異なるコンポーネントを使用ホームページを作成いたします。.
のビルダをインストールパターンのアルゴリズムカプセル化され、取締役のに対し、ビルダーを作成するのに使われまでの一体部品です。を変化させて使用builderのアルゴリズムの取締役の結果と異なる表現でその他の部品で構成されるメニューです。のメニューの作成に変更はありません。
工場:ントを作成するためのオブジェクトのインスタンスに依存関係のオブジェクトの全ての工場です。のための 抽象パターン工場, がしばしば多くのコンクリート実装では、同じ概要工場です。右の実施に工場を注入することで経由依存性。
ビルダー:を構築するのに使用 不変なので 物が依存するオブジェクトがインスタンスを生成しても知られる前に、一部お客様にご提供いただくのビルダを構築します。
の違いは明らかです Builderパターンでは、ビルダーは、あなたのための特定のタイプのオブジェクトを作成します。あなたは何を伝える必要があります ビルダーは、構築することがあります。 工場出荷時のパターンでは、抽象クラスを使用すると、あなたは直接特定のオブジェクトを構築しています。
メインクラスと、特定の種類のクラス間の仲介者としてここでは、ビルダークラスの役割を果たします。 もっと抽象ます。
の両方が非常に似ていますが、いくつかのデフォルト値を持つオプションのうちのいくつかを持つオブジェクトを作成するための多数のパラメータを持っている場合、Builderパターンのために行く。
私は/の使用状況や工場&Builderのパターンの違いを理解することができる、と信じては、一定の期間内に容易に明らかにしました。
私の経験から、通常、あなたは、静的なクリエイターメソッドのカップルを含むFactoryパターンで始まります。あなたのオブジェクト階層がより複雑になるにつれ(またはあなたがより多くの種類を追加すると)、あなたはおそらく、あなたの方法は、より多くのパラメータが移入し、あなたがつもり、あなたの工場のモジュールを再コンパイルする必要は言及しないように持って終わります。これらすべてのものは、あなたのクリエイター方法の複雑さを増大させ、読みやすさを減少させ、生成モジュールは、より脆いになります。
この点は、おそらく遷移点であろう。工場からビルダーパターンへの移行。そうすることによって、あなたはの建設・パラメータの周りにラッパーモジュールを作成をして、あなたができるようになりますが、実際のあなたの作成ロジックに触れずに、いくつかのより多くの抽象化(おそらく)と実装を追加することによって、新たな(似た)オブジェクトを表します。ですから、あまり複雑なロジックと、再コンパイルされたソースコードを持っていた。
私は、ほぼすべてのケースのための両方の方法を使用することができますので、私はそれらを区別するために、率直に言って、唯一の多様性の要因として、「違いをワンステップまたは複数のステップで作成されたオブジェクトをされた」の何かの並べ替えを参照するだけでは十分ではなかったIすべての利益を経験することなく、今までに直面しました。だから、これは私が最終的にそれについて考えてきたものです。
主にこれらの差額については、ビルダをインストールパターン 主として を作成する方法について述べ複雑なオブジェクト。の概要工場でのパターンを重視 家族の物品.ビルダーを返します製品の 最後のステップ.の抽象パターン工場の製品 すぐに利用可能.
例:せて行うことを迷路
1.概要工場:
Maze* MazeGame::CreateMaze (MazeFactory& factory) {
Maze* maze = factory.MakeMaze(); /// product is available at start!!
/* Call some methods on maze */
return maze;
}
2.ビルダー:
Maze* MazeGame::CreateMaze (MazeBuilder& builder) {
builder.buildMaze(); /// We don't have access to maze
/* Call some methods on builder */
return builder.GetMaze();
}
ビルドパターンで強調の複雑さ( "段階" によって解決)オブジェクトを作成する
抽象パターン(複数が関連)オブジェクトの「抽象」の「だけ」を強調している。
私の意見では Builderパターンを使用すると、他のオブジェクトと一部の創造の束からオブジェクトを作成する場合、作成するオブジェクトとは独立である必要が使用されています。これは、ビルダーと、クライアントは独立させるために、クライアントからの部品の作成を非表示にすることができます。これは、複雑なオブジェクトの作成(複雑な性質のためかもしれないからなるオブジェクト)のために使用されている
ファクトリパターンを使用すると、一般的な家庭のオブジェクトを作成したいとあなたはそれが一度にセレイテッド型にしたいことを指定しますが。これは、単純なオブジェクトに使用されます。
まぁ
ビルダーが一部のような複雑な工場です。
が でビルダーできるインスタンスを生成オブジェクトを別の工場, このビルドに必要な最終有効なオブジェクトです。
なので、話"Creationalパターンの"進化により複雑化するようになってきています:
Dependency Injection Container -> Service Locator -> Builder -> Factory
ビルダーと抽象ファクトリー
Builderのデザインパターンは、抽象的なFactoryパターンに、ある程度で、非常によく似ています。どちらか一方が使用されている状況との違いを作ることができることが重要である理由です。抽象工場の場合、クライアントは、独自のオブジェクトを作成するために、工場のメソッドを使用しています。 Builderの場合は、ビルダークラスは、オブジェクトを作成する方法について指示されているし、それはそれを求めているが、クラスが一緒に置かれている方法は、この詳細は、二つのパターンの違いを作り、ビルダークラスまでです。
製品の共通インターフェース
別の製品に共通の親クラスを派生する理由がないので、もし実際には具体的なビルダーで作成された製品は、大幅に異なる構造を有しています。また、これは一般的なタイプから派生したオブジェクトを作成し、Abstract Factoryパターンからビルダーパターンを区別します。
両方のパターン越しの必要性:隠れからクライアントコードを構築論理の複雑なオブジェクトです。でもこの"複合"(または、複雑なオブジェクト?主にしてくれているのですが、依存関係のため、というの状態でオブジェクトの構成による部分です。き注入依存関係によるコンストラクタ設定を初期オブジェクトの状態でオブジェクトが必要となく、このままデフォルトの初期状態でいた設定デフォルトの依存関係をnullにはない最もきれいになるという事ではなく他のセット状態で駆動します。また、オブジェクトのプロパティがあの"忘依存関係"もっとオプションです。
が知られ方を支配する複雑さ:
組成、成分の凝集:を構築し、オブジェクトを構築しそれに依存するオブジェ、そのワイヤーです。ここでは、ビルダーで透明性と柔軟性の工程を決めるルールを構築す。
多型:建築のルールを宣言した直接サブタイプの定義ですから、一定のルールは各サブタイプの一部条件を決めるこれらの規則の適用を構築するオブジェクトです。工場合にもこのシナリオ。
何を防止するミックスこれらの二つのアプローチをとる。家族の商品が抽象オブジェクトの創出を行っていたビルダーは、ビルダーが使用工場を決定するコンポーネントオブジェクトのインスタンスを生成.
Factoryパターンは、すなわち、その主な目的は、サブクラスがインスタンス化するクラスを決定できるようにする多型を使用することで、実行時にクラスの具体的な実装を作成します。これは、我々はビルダーパターンは、クラスのオプションフィールドの多数により生じるアンチパターン伸縮式コンストラクタの問題を解決すると、主に懸念している一方で、作成される正確なクラスを知らないコンパイル時に意味しています。私たちは、コンパイル時に構築しようとしているものを対象知っているようにBuilderパターンでは、多型という概念はありません。
これら二つのパターンの唯一の共通のテーマは、改善されたオブジェクトの構築のためのコンストラクタの隠蔽とファクトリメソッドの背後にあるオブジェクトの作成、および構築方法である。
Factoryパターンは、Builderパターンを使用すると、オブジェクトの作成プロセスを中断させながら、一度に一度にオブジェクトを作成してみましょう。このように、あなたは、オブジェクトの作成中に別の機能を追加することができます。