私はこの質問が以前に尋ねられたことを知っています(例えば ブリッジパターンと戦略パターンの違いは何ですか? )。
しかし、誰かが明確な例を使用して、違いは何であり、どのような場合に一方を他方よりも選択する必要があるかを説明できますか?概念理論ではなく、より実用的な「現実の」シナリオをいただければ幸いです。
ブリッジパターンは、抽象化と実装を区別して、2つが独立して変化できるようにします。からの例を使用します
Javaのパターン、第1巻:UMLで説明されている再利用可能なデザインパターンのカタログ、第2版
はかりや速度測定装置などにある物理センサーにアクセスするクラスを提供する必要があります。各センサーは数値を生成しますが、数値は異なる意味を持つ可能性があります。体重計の場合は重量を意味し、速度測定装置の場合は速度を意味する場合があります。
したがって、すべてのセンサーとさまざまなタイプのセンサーのさまざまなサブクラスとの間の共通性を表すセンサー抽象クラスを作成することから始めることができます。これは堅牢な設計であり、将来、より多くの種類のセンサーを提供できるようになります。
ここで、センサーがさまざまなメーカーから提供されているとします。メーカーX用とメーカーY用のセンサークラスの階層を作成する必要があります。問題は、クライアントがメーカー間の違いを知る必要があるということです。そして、あなたがサードメーカーをサポートすることに決めたら...?
解決策は、主要な抽象化階層を提供することです。センサーの抽象クラスと、SpeedSensorやWeightSensorなどのサブクラス。次に、抽象化と実装の間に存在するインターフェース(ブリッジ)を提供します。したがって、SensorInterface、WeightSensorInterface、SpeedSensorInterfaceがあり、これらは各具象センサークラスが提供する必要のあるインターフェースを指示します。抽象化は実装については知りませんが、インターフェースについては知っています。最後に、メーカーごとにconcreate実装を作成できます。つまり、XSensor、XWeightSensor、XSpeedSensor、YSensor、YSpeedSensor、YWeightSensorです。
クライアントは抽象化のみに依存しますが、任意の実装をプラグインできます。したがって、このセットアップでは、具象クラスを変更せずに抽象化を変更でき、抽象化を気にせずに実装を変更できます。
ご覧のとおり、これはクラスを構造化する方法を説明しています。
一方、ストラテジーは、実行時のオブジェクトの動作の変更に関係しています。いくつかの異なる種類の武器を持っているキャラクターを使ったゲームの例を使用するのが好きです。キャラクターは攻撃できますが、攻撃の動作はキャラクターがその時に持っている武器に依存し、これはコンパイル時に知ることはできません。
したがって、武器の動作をプラグ可能にし、必要に応じてキャラクターに注入します。したがって、行動パターン。
これらの2つのパターンは、異なる問題を解決します。戦略はアルゴリズムを交換可能にすることに関係し、Bridgeは抽象化を実装から切り離すことに関係しているため、同じ抽象化に対して複数の実装を提供できます。つまり、橋は構造全体に関係しています。
役に立つかもしれないいくつかのリンクはここにあります:
これを説明するのは難しいと言えます。それを使用して理解している多くの人々は、それを初心者に説明するのに苦労しています。
類推の観点から考える私のような人のために:
つまり、戦略は一種の一次元の概念です。選択する戦略の1次元配列を考えてみてください。
戦略パターンは、パイプの詰まりを取り除くためのさまざまなツールを備えた配管工のようなものです。仕事は毎回同じです。パイプの詰まりを取り除くことです。しかし、これを実現するために彼が選択するツールは、状況によって異なります。たぶん彼は1つを試し、それがうまくいかない場合は別の1つを試します。
この例えでは、「パイプの詰まりを取り除く」は、戦略の1つを実装する方法です。スネークブラシ、パワーオーガー、およびドレイノは具体的な戦略であり、配管工はメソッドを含むクラスです(ほとんどの図で「コンテキスト」とラベル付けされています)。
または、マルチビットドライバーの交換可能なビットについて考えることもできます。それらは、何かをねじ込むという目前の仕事に合うように、実行時に変更されることを意図しています。
つまり、ブリッジは2次元の概念です。 1つの次元(行)は実装する必要のあるメソッドのリストであり、2番目の次元(列)はそれらのメソッドのそれぞれを実装する実装者であると考えてください。
ブリッジパターンは、さまざまな方法で通信できる人(メール、テキスト、Google Voice、電話、Skype)と、さまざまな方法で通信できる多くのデバイス(PC、タブレット、スマート)のようなものです。電話。
通信するためのさまざまな方法(電子メール、テキスト、電話)は、抽象インターフェースのメソッドであり、「CommunicationDevice」と呼びましょう。このパターンでは、CommunicationDeviceが実装者です。この例えの各デバイス(PC、タブレット、スマートフォン)は、これらすべてのメソッド(電子メール、テキスト、電話)を実装するConcreteImplementorです。
ブリッジのもう1つの簡単な例は、Windowsのodbcまたはoledbデータベースドライバーモジュールです。これらはすべて、同じ標準の「データベースドライバ」インターフェイスにさまざまなメソッドを実装していますが、そのインターフェイスはさまざまな方法で実装されています。同じデータベース、たとえばSql Serverを使用している場合でも、内部ではさまざまな方法ではありますが、SqlServerと通信できるさまざまなドライバーがあります。
このパターンにより、実行するアルゴリズムは、それを使用するクライアントとは独立して変化します。つまり、特定の状況で実行する固定アルゴリズムの代わりに、実行時にオンザフライで選択される多くのアルゴリズムの1つを許可します。これには、ホストクラスからアルゴリズムを削除し、それを別のクラスに配置することが含まれます。
たとえば、ある都市から別の都市に移動したい場合、バスに乗る、レンタカーを借りる、電車に乗るなど、いくつかの選択肢があります。したがって、選択した各交通手段は、実行される個別のアルゴリズムになります。選択される輸送モードは、実行時に決定されるさまざまな要因(コスト、時間など)によって異なります。言い換えれば、実行するために選択された戦略はその場で決定されます。
別の例として、SortedList
に基づいてSorts
であるstrategy
クラス(メインコントローラー)を実装したいとします。戦略は、ソートに使用する方法です(MergeSort、QuickSortなど)。
主な違いは(両方のパターンが同じUMLを持っている場合でも)、ブリッジパターン(構造パターン)とは異なり、戦略パターンは行動パターンであるということです。構造パターンは、オブジェクトを構成、関連付け、または継承して、より大きなオブジェクトを形成する方法を示します。つまり、オブジェクトの構成に焦点を合わせます。行動パターンはアルゴリズムまたはビジネスロジックを扱いますが(オブジェクトの作成自体ではありません)、つまり、オブジェクト間のコラボレーションに焦点を合わせます。
ほとんどのアルゴリズムは、単一インスタンスの作成のみを必要とする静的クラスまたはシングルトンクラスとして実装できることに注意してください(つまり、戦略が設定されるたびにnew
が呼び出されるわけではありません)。
2つのパターンの実装を詳しく見ると、ブリッジパターンで、オブジェクトの具体的な実装を作成してから、呼び出しを作成することがわかります。
// Set implementation and call
// i.e. Returns (creates) the concrete implementation of the object,
// subsequently operation is called on the concrete implementation
ab.Implementor = new ConcreteImplementorA();
ab.Operation();
戦略パターンの場合、アルゴリズムの具体的な実装を直接使用するのではなく、戦略を実行するコンテキストを作成します。
// Set the context with a strategy
// i.e. Sets the concrete strategy into the context, concrete implementation of the class not
// directly available as a data object (only the algorithm is available).
context = new Context (new ConcreteStrategyA());
context.contextInterface();
// Strategy can be reused instead of creating a new instance every time it is used.
// Sort example
MergeSort mergeSort = new MergeSort();
QuickSort quickSort = new QuickSort();
...
context = new Context (mergeSort);
context.Sort();
...
context = new Context (quickSort);
context.Sort();
...
context = new Context (mergeSort);
context.Sort();
ブリッジパターンは、クラスの編成方法、戦略、つまりアルゴリズムの編成方法を示します。
ストラテジーパターンはアルゴリズムをカプセル化して、複雑なプログラムで使用および変更できるようにします(作業を無駄にすることなく)。ブリッジパターンでは、2つのインターフェイスを緩くバインドして、相互作用できるが互いに独立して変更できるようにします。
PHPブリッジとストラテジーパターンの例はここにあります:
http://www.php5dp.com/category/design-patterns/bridge/
そして
http://www.php5dp.com/category/design-patterns/strategy/
両方のパターンの例がたくさんあり、役立つ場合があります。
どちらのパターンも、インターフェースを実装から分離します。主な違いは、ブリッジパターンが継承(「isa」)を使用するのに対し、ストラテジーパターンは構成(「hasa」)を使用することだと思います。
ブリッジパターン:
class Sorter abstract
{
virtual void Sort() = 0;
}
// MergeSorter IS A Sorter
class MergeSorter : public Sorter
{
virtual void Sort() override;
}
戦略パターン:
class SortStrategy abstract
{
virtual void Sort() = 0;
}
// Sorter HAS A SortStrategy
class Sorter
{
Sorter(SortStragety *strategy) : mStrat(strategy) {}
void Sort() {mStrat->Sort();}
SortStrategy *mStrat;
}
戦略:
Strategyは動作設計パターンです。アルゴリズムのファミリーを切り替えるために使用される場合。
このパターンには、1つの抽象戦略インターフェイスと多くの具体的な戦略の実装(そのインターフェースのアルゴリズム)。
アプリケーションは戦略インターフェースのみを使用します。一部の構成パラメーターに応じて、具体的な戦略はインターフェースにタグ付けされます。
ブリッジ:
例えばArrayList
によって実装されたJava.util. List
のコレクションクラス。
しかし、誰かが明確な例を使用して、違いは何であり、どのような場合に一方を他方よりも選択する必要があるかを説明できますか?
ストラテジーとブリッジパターンのユースケースに関する洞察を得るために、以下の投稿を参照してください。
簡単なメモ:
Strategyパターンを使用して、ある戦略を他の戦略に置き換えることにより、実装を動的に変更します。
1つの実際のWordの例:オフピーク月に割引を提供する航空会社。ピーク時に割引なしの戦略で運賃割引戦略を変更するだけです。
抽象化と実装がコンパイル時に決定されておらず、独立して変化する可能性がある場合は、Bridgeパターンを使用します
自動車産業における実例の1つ:さまざまなタイプの歯車をさまざまなタイプの車。 CarとGearの仕様と実装はどちらも独立して変更できます。
リンクされた質問からの答えを暗唱させてください。
ブリッジパターンは構造パターンです。つまり、プロジェクトのコンポーネントを構築する方法のアイデアをレイアウトします。これは、2つのレベルの抽象化を非表示にするために使用されます。ウィキペディア(http://en.wikipedia.org/wiki/Bridge_pattern)のサンプルコードは、最も明確な用語でそれを説明しています。
戦略パターンは動的パターンです。ワイルド関数が要件を実装できる場合、戦略パターンが使用されます。例としては、プラグインの開発とインストールを可能にする任意のプログラムがあります。ウィキペディアのページ(http://en.wikipedia.org/wiki/Strategy_pattern)では、ConcreteStrategyAdd、ConcreteStrategySubtractなどがConcreteStrategyクラスで使用されるプラグインです。そこでは、インターフェースStrategyを実装する任意のメソッドを使用できます。
ブリッジパターンは、現在の状況に従ってビジネス構造を実行しながら、再実装する機能を提供します。反対側の戦略パターンは、さまざまなビジネス戦略を実装し、それらをカプセル化して、状況ごとに、または一度に使用する機能を提供します。
両者の主な違いは、ブリッジパターンを使用して全体の構造を変更できることですが、戦略を使用すると、ビジネス戦略を並行して変更できます。
私の理解に従って、以下に2つの非常に重要な設計パターンを詳しく説明しました。慎重に投げに行ってください。両方についての理解が深まると思います。
GoFが提案するブリッジパターンの意味は、コンポーネントの実装をその抽象化から切り離すことです。
コンポーネントがすでに実装されており、ビジネスニーズに従って正常に実行されている状況を想像してみてください。突然、組織はビジネス戦略を変更しました。このためには、コンポーネントを変更または再実装する必要があります。この状況で、何をするかによって、過去数年間正常に実行されていた以前のコンポーネントを変更するか、新しいコンポーネントを作成します。この状況では、ブリッジパターンがシナリオを美しく処理しました。理解を深めるには、以下の例を参照してください。
// Main component
public interface Ibridge
{
void function1();
}
// Already Implemented that are currently being using
public class Bridge1 : Ibridge
{
public void function1()
{
Console.WriteLine("Implemented function from bridge 1");
}
}
//New Implementation as per Organisation needs
public class Bridge2 : Ibridge
{
public void function1()
{
Console.WriteLine("Implemented function from bridge2");
}
}
//Abstract Calling functionalities
public interface IAbstractBridge
{
void CallFunc1();
}
// implementation of calling implemented component at a time
public class AbstractBridge:IAbstractBridge
{
protected Ibridge _ibridge;
public Ibridge Ibridge
{
set { _ibridge = value; }
}
public void CallFunc1()
{
this._ibridge.function1();
}
}
class Program
{
static void Main(string[] args)
{
AbstractBridge abp = new AbstractBridge();
/*
here you see that now being using the previous implemented component.
but need change newly implemented component so here we need just changed
the implementation of component, please see below
*/
//Commented old one
abp.Ibridge = new Bridge1();
//using new one just change the "Bridge1" to "Bridge2"
abp.Ibridge = new Bridge2();
abp.CallFunc1();
}
}
GoFが提案する戦略パターンの意味は、アルゴリズムのファミリーを定義し、それぞれをカプセル化し、それらを交換可能にすることです。ストラテジーにより、アルゴリズムはそれを使用するクライアントとは独立して変化します。
ショッピングセンターの所有者が、さまざまな機会に基づいて異なる割引オファーを提供する顧客を引き付けたい状況を想像してみてください。所有者が割引モードから通常モードに、またはその逆に切り替えることができるときはいつでも、割引オファーを提供します。この状況での対処方法戦略パターンがシナリオを処理しました。理解を深めるために、以下の例を参照してください。
public interface ISellingStrategy
{
void selling();
}
public class BasicStrategy : ISellingStrategy
{
public void selling()
{
Console.WriteLine("Buy Three get 5% discount.");
}
}
public class ChrismasStrategy : ISellingStrategy
{
public void selling()
{
Console.WriteLine("Buy Three get one offer + extra 5% discount.");
}
}
public class HoliFestiveStrategy : ISellingStrategy
{
public void selling()
{
Console.WriteLine("Buy two get one offer + extra 5% discount.");
}
}
public class DurgapuljaStrategy : ISellingStrategy
{
public void selling()
{
Console.WriteLine("Buy one get one offer + extra 5% discount.");
}
}
public class Billing
{
private ISellingStrategy strategy;
public void SetStrategy(ISellingStrategy _strategy)
{
this.strategy = _strategy;
}
public void ApplyStrategy()
{
strategy.selling();
Console.WriteLine("Please wait offer is being applying...");
Console.WriteLine("Offer is now Applied and ready for billing..");
}
}
public class BillingFactory
{
public static Billing CreateBillingObject()
{
return new Billing();
}
}
class Program
{
static void Main(string[] args)
{
Billing billing = BillingFactory.CreateBillingObject();
billing.SetStrategy(new BasicStrategy());
billing.ApplyStrategy();
Console.ReadLine();
}
}