ブリッジパターンと戦略パターンの違いは何ですか?


114

dofactoryやwikipedia、そして多くのサイトに関する多くの記事を読もうとしました。ブリッジパターンと戦略パターンの違いはわかりません。

どちらも抽象化を実装から切り離し、実行時に実装を変更できることを知っています。

しかし、どのような状況で戦略を使用する必要があるのか​​、またはどのような状況でブリッジを使用する必要があるのか​​はまだわかりません。

回答:


66

セマンティクス。ウィキペディアから:

StrategyパターンのUMLクラス図は、Bridgeパターンの図と同じです。ただし、これら2つの設計パターンの意図は同じではありません。Strategyパターンは動作を目的としていますが、Bridgeパターンは構造を目的としています。

コンテキストと戦略の間の結合は、抽象化とBridgeパターンの実装の間の結合よりも緊密です。

私が理解しているように、外部ソースから提供される可能性のある動作を抽象化している場合(たとえば、configがプラグインアセンブリをロードするように指定できる場合)にストラテジーパターンを使用しており、使用時にブリッジパターンを使用しているコードを少しすっきりさせる同じ構成要素。実際のコードは非常によく似ています- わずかに異なる理由でパターンを適用しているだけです。


3
戦略パターンを使用して動作を抽象化しながら、コードをブリッジパターンのようにすっきりと見せているとも言えます。または、ブリッジパターンを使用してコードをすっきりさせることもできます。戦略パターンのような行動を抽象化するには?そして私は正しいでしょうか?
user20358

1
両者の違いは、その意図のみです。したがって、どちらも同じアイデアを使用し、同じ柔軟性を提供するため、2つのパターンは機能的には同じであると言えます。
Elz

3
BridgeのUMLは、私のGoF本のコピーではかなり異なります。 このツールは、BridgeとStrategyを区別することができます。
Fuhrmanator 16

1
ウィキペディアはしばしばひどいリファレンスです。間違いなく、その誤った情報はページから削除されました。en.wikipedia.org/w/...
Fuhrmanator

2
私が得る方法は、同じ手法を使用して実装を抽象化する(戦略)か、インターフェイスを抽象化する(ブリッジ)ことです。戦略は動作を交換し、ブリッジはインターフェースを交換します(これにより、最終的にはそのようなインターフェースを持つ実装を交換できます)。言い換えると、ブリッジは一方の側に標準化されたインターフェースを作成し、もう一方のインターフェースに異なる実装をプラグインします。
Nikaas

55

ブリッジパターンは構造パターンです(ソフトウェアコンポーネントをどのように構築しますか?)。戦略パターンは動的パターンです(ソフトウェアで動作を実行する方法を教えてください)。

構文は似ていますが、目的は異なります。

  • 戦略:操作を行うためのより多くの方法があります。ストラテジーを使用すると、実行時にアルゴリズムを選択でき、コンパイル時に多くの副作用なしに単一のストラテジーを変更できます。
  • ブリッジ:インターフェイスとクラスの階層を分割し、抽象参照で結合できます(説明を参照)

3
したがって、構文が似ている場合、これらのパターンのいずれかを使用して特定の方法でソフトウェアの動作を実行していること、およびコンポーネントをそのように構築して見栄えをよくしたいという理由で正しいでしょうか?
user20358

11

戦略:

  • 戦略に関連付けられたコンテキスト:コンテキストクラス(抽象ではあるが実際にはインターフェースではない!特定の動作をカプセル化し、実装全体をカプセル化したくない場合)は、戦略のインターフェース参照と、戦略の動作を呼び出す実装を知っている/含みます。それ。
  • インテントは、実行時に動作を交換する機能です

    class Context {
    
         IStrategy strategyReference;
    
         void strategicBehaviour() {
    
            strategyReference.behave();
         }
    
    }
    

ブリッジ

  • 抽象化は実装に結び付けられていない:抽象化インターフェース(または動作の抽象化の大部分を備えた抽象クラス)は、実装インターフェース参照を知らない/含まない
  • 目的は、抽象化を実装から完全に切り離すことです

    interface IAbstraction {
    
        void behaviour1();
    
        .....
    
    }
    
    interface IImplementation {
    
         void behave1();
    
         void behave2();
    
         .....
    
    }
    
    class ConcreteAbstraction1 implements IAbstraction {
    
          IImplementation implmentReference;
    
          ConcreteAbstraction1() {
    
               implmentReference = new ImplementationA() // Some implementation
    
          }
    
          void behaviour1() {
    
                implmentReference.behave1();
    
          }
    
          .............
    
    }
    
    class ConcreteAbstraction2 implements IAbstraction {
    
          IImplementation implmentReference;
    
          ConcreteAbstraction1() {
    
               implmentReference = new ImplementationB() // Some Other implementation
    
          }
    
          void behaviour1() {
    
                implmentReference.behave2();
    
          }
    
          .............
    
    }
    

10

私は同じことを考えていましたが、最近、ブリッジを使用する必要があり、ブリッジが戦略を使用し、コンテキストに抽象化を追加しているため、後でクライアントを変更せずにさらに変更を加えることができることに気付きました。抽象化せずに戦略を使用する場合、設計はそれほど柔軟ではなく、後でクライアントに変更を加える必要があるかもしれません。しかし、ブリッジ全体を使用すると、設計はさらに柔軟になります。ここでは、戦略からブリッジに移行することで、柔軟性がどのように向上するかを確認できます。また、「ビザ」と「マスター」はカードだけでなく、電話やチップでも利用できると想定しています。ブリッジを使用すると、サポートを追加するのがはるかに簡単になります。

戦略VSブリッジ


9

ブリッジ:(構造パターン)

ブリッジパターンは、抽象化と実装を分離し、両方を独立して変更できるようにします。

このパターンは次の場合に使用します。

  1. 抽象化と実装はコンパイル時に決定されていません
  2. 抽象化と実装は個別に変更する必要があります
  3. 抽象化の実装の変更は、呼び出し元アプリケーションに影響を与えるべきではありません
  4. クライアントは、実装の詳細から隔離する必要があります。

戦略:行動パターン)

戦略パターンを使用すると、実行時にアルゴリズムファミリーの複数のアルゴリズムを切り替えることができます。

戦略パターンは次の場合に使用します。

  1. アルゴリズムの複数のバージョンが必要です
  2. クラスの動作は実行時に動的に変更する必要があります
  3. 条件付きステートメントを避ける

関連記事:

いつブリッジパターンを使用しますか?アダプターパターンとどう違うのですか?

戦略パターンの実例


4

デザインパターンタイプ

  • 行動:パターンは、クラスまたはオブジェクトが相互作用し、責任を分散する方法を特徴付けます
  • 構造:パターンはクラスまたはオブジェクトの構成を扱います。
  • 作成: パターンはオブジェクト作成のプロセスに関係します。

(構造)

抽象化を実装から切り離して、それぞれが異なるようにします。独立して。 ここに画像の説明を入力してください

リモコンを取る。リモコンにはボタン1〜6があります。これは、上の図の具象クラスです。リモコンがテレビまたはDVDに使用されているかどうかに応じて、各ボタンの動作は異なります。各ボタンの機能は、実装者インターフェースによって実装から抽象化されています。

これにより、各デバイスのリモコンの動作を変更できます。

戦略(行動)

アルゴリズムのファミリーを定義し、それぞれをカプセル化して、それらを交換可能にします。 ここに画像の説明を入力してください

戦略では、リモートシナリオを見ていた場合。「状態」は、コンテキスト全体の状態参照を変更することで交換するリモート全体です。"concreteStateA"(TVリモート) "concreteStateB"(DVDリモート)。

追加の読み:


3
  1. 戦略パターンは行動の決定に使用され、ブリッジパターンは構造の決定に使用されます。

  2. Brigdeパターンは実装の詳細から抽象的な要素を分離しますが、戦略パターンはアルゴリズムをより交換可能にすることを考慮しています。

UMLの戦略パターン

UMLの旅団パターン

Swiftの戦略パターン:

protocol PrintStrategy {
   func print(_ string: String) -> String
}

class Printer {
   let strategy: PrintStrategy

   init(strategy: PrintStrategy) {
      self.strategy = strategy
    }

  func print(_ string: String) -> String {
     return self.strategy.print(string)
  }
}

class UpperCaseStrategy: PrintStrategy {
    internal func print(_ string: String) -> String {
        return string.uppercased()
    }
}

class LowerCaseStrategy: PrintStrategy {
    internal func print(_ string: String) -> String {
        return string.lowercased()
    }
}

var lower = Printer(strategy: LowerCaseStrategy())
lower.print("I love Software Patterns")

var upper = Printer(strategy: UpperCaseStrategy())
upper.print("I love Software Patterns")

Swiftのブリッジパターン:

protocol Appliance {
   func run()
}

protocol Switch {
   let appliance: Appliance {get set}
   func turnOn()
}

class RemoteControl: Switch {
   var appliance: Appliance

   init(appliance: Appliance) {
       self.appliance = appliance
   }

   internal func turnOn() {
      appliance.run()
   }
}

class TV: Appliance {
   internal func run() {
      print("TV is ON")
   }
}

class Stereo: Appliance {
   internal func run() {
      print("Stereo is ON")
   }
}

var tvRemote = RemoteControl.init(appliance: TV())
tvRemote.turnOn()

var stereoRemote = RemoteControl.init(appliance: Stereo())
stereoRemote.turnOn()

どうして戦略パターンだけがより「交換可能」になるのか。あなたはスワップ、あなたのコード例で示すようにインタフェースにではなく、実装に我々のコードので、私たちは、戦略の実装、またはブリッジを入れ替えることができStereoTV、コードだけで動作します。
denis631

2

willcodejavaforfoodの答えに追加すると、実装では同じになる可能性があります。ただし、戦略を使用してソート戦略などの戦略を入れ替える一方で、ブリッジを使用して2つのオブジェクト(データベースラッパーなど)とネットワークアダプターの実装をブリッジし、クライアントコードが同じAPIに対して機能するどちらかを使用できるようにします。だからネーミングは実際にそれをすべて言います


1

戦略パターンに関するウィキから

StrategyパターンのUMLクラス図は、Bridgeパターンの図と同じです。ただし、これら2つの設計パターンの意図は同じではありません。Strategyパターンは動作を目的としていますが、Bridgeパターンは構造を目的としています。

コンテキストと戦略の間の結合は、抽象化とBridgeパターンの実装の間の結合よりも緊密です。


最後のフレーズを詳しく説明してもらえますか?
gstackoverflow

1

パターン比較についてすでに述べられていることを追加するために(意図の違いなど):Bridgeパターンも意図的に構造化されており、抽象化階層の側を変えることができます。C#のような言語では、これは、既存のコンシューマーに問題を引き起こさない意図したバリエーションを許可する方法として、仮想メソッドを含む抽象化ベースがあることを意味します。それ以外は、2つのパターンはほとんど同じように見える場合があります。


1

戦略パターンは、実行時にアルゴリズムまたは戦略をプラグインするときに使用されます。パターンのカテゴリは、オブジェクトの動作を処理することも意味します。一方、ブリッジは構造パターンであり、オブジェクトの構造階層を扱います。それらの間で洗練された抽象化を導入することにより、実装から抽象化を切り離します。洗練された抽象化は、プラグインされた実行時戦略(戦略パターン内)と混同される可能性があります。ブリッジパターンは、n個のクラスの作成を回避するメカニズムを提供することにより、構造的側面を扱います。


1

戦略パターンの場合、実装のみが異なります。

クラスAが、利用可能な複数の実装を持つクラスBを使用しているとします。したがって、その場合、Bは実行時に提供される実際の実装で抽象的です。これは戦略パターンです

ここで、A自体が抽象である場合。AとBの両方が異なる場合があります。ブリッジパターンを使用します。


0

それらが使用されているコンテキストでは、それらの間にわずかな違いがあると思います。

私はブリッジパターンを使用して、両方がより大きなものに属する直交する概念を分離します-それらを独立して変化させることができます。通常、これには複数の抽象化が含まれます。

IMO、戦略パターンはより単純またはよりフラットです。それは確かにOCPに役立ちますが、必ずしもBridgeパターンのような別のより大きな概念の一部である必要はありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.