web-dev-qa-db-ja.com

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

dofactory 、wikipedia、多くのサイトで多くの記事を読みました。ブリッジパターンと戦略パターンの違いについてはわかりません。

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

しかし、どの状況で戦略を使用すべきか、どの状況でブリッジを使用すべきかはまだわかりません。

109
Krirk

セマンティクス。 wikipedia から:

StrategyパターンのUMLクラス図は、Bridgeパターンの図と同じです。ただし、これら2つの設計パターンは、意図が同じではありません。戦略パターンは行動を意味しますが、ブリッジパターンは構造を意味します。

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

私が理解しているように、外部ソースから提供できる動作を抽象化するときに戦略パターンを使用しています(たとえば、configはプラグインアセンブリを読み込むように指定できます)。使用するときはブリッジパターンを使用していますコードを少し見やすくするための同じ構成体。実際のコードは非常によく似ています-わずかに異なる理由でパターンを適用しているだけです

62
Kent Boogaart

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

構文は似ていますが、目標は異なります:

  • 戦略:操作を行う方法は他にもあります。戦略を使用すると、実行時にアルゴリズムを選択でき、コンパイル時に多くの副作用なしに単一の戦略を変更できます。
  • Bridge:インターフェイスとクラスの階層を分割し、抽象参照で結合できます( explication を参照)
53
alepuzio

戦略:

  • 戦略に関連付けられたコンテキスト:コンテキストクラス(おそらく抽象的ですが、実際にはインターフェイスではありません!実装全体ではなく特定の動作をカプセル化するため)は、戦略インターフェイスの参照と実装 =その戦略行動を呼び出す。
  • 意図は実行時に動作を交換する能力です

    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
MEER

Bridge(構造パターン)

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

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

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

戦略:(行動パターン)

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

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

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

関連記事:

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

戦略パターンの実世界の例

8
Ravindra babu

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

Strategy VS Bridge

5
Orhan

デザインパターンタイプ

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

ブリッジ (構造)

それぞれが異なるように、抽象化をその実装から分離します。独立して。 enter image description here

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

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

戦略 (行動)

アルゴリズムのファミリーを定義し、それぞれをカプセル化し、それらを交換可能にします。 enter image description here

戦略では、リモートシナリオを検討していました。 「状態」とは、コンテキストの状態参照を変更することでスワップアウトするリモート全体です。 「concreteStateA」(TVリモート)「concreteStateB」(DVDリモート)。

追加の読み物:

3
Daniel

Willcodejavaforfoodの答えに加えて、実装において同じにすることができます。ただし、戦略を使用してソート戦略などの戦略を交換し、ブリッジを使用して2つのオブジェクト(データベースラッパーとネットワークアダプターなど)の実装をブリッジして、クライアントコードが同じAPIに対して動作するようにします。それで、命名は実際にそれをすべて言います

2
Robert Gould
  1. Strategyパターンは行動決定に使用され、Bridgeパターンは構造的な決定。

  2. Brigdeパターンは実装の詳細から抽象要素を分離し、Strategyパターンアルゴリズムの互換性を高めることに関心があります。

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()
2
Joan Disho

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

1
Burt

Strategy patternのウィキから

StrategyパターンのUMLクラス図は、Bridgeパターンの図と同じです。ただし、これら2つの設計パターンは、意図が同じではありません。戦略パターンは行動を意味しますが、ブリッジパターンは構造を意味します。

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

1

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

1
Pranav Sharma

戦略パターンについては、実装のみが異なります。

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

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

0
Ritesh Tyagi

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

ブリッジパターンを使用して、両方がより大きな概念に属する直交概念を分離します。通常、複数の抽象化が含まれます。

IMO、戦略パターンはよりシンプルまたはよりフラットです。確かにOCPに役立ちますが、必ずしもブリッジパターンのような別のより大きなコンセプトの一部である必要はありません。

0
stdout