web-dev-qa-db-ja.com

BridgeパターンとAdapterパターンの違い

ブリッジとアダプターのパターンの違いは何ですか?

105
Firoz

「アダプターは、設計された後に物事を機能させます。ブリッジは、それらが機能する前に機能します。[GoF、p219]」

事実上、Adapterパターンは、既存のコードがある場合、サードパーティであろうと社内であろうと、あなたの制御が及ばない場合、または必要なインターフェースに完全に適合するように変更できない場合に役立ちます。たとえば、終末のデバイスの細かい配列を制御できるSuperWeaponsArrayがあります。

public class SuperWeaponsArray {
  /*...*/

  public void destroyWorld() {
    for (Weapon w : armedWeapons) {
      w.fire();
    }
  }
}

すばらしいです。武器インターフェースへの変換よりもはるかに前の核兵器が武器庫にあることを認識している場合を除きます。しかし、ここで動作することを本当に望んでいます...それで、私たちは何をしますか...それを押し込んでください!

NukeWeaponsAdaptor-Nukeクラスに基づいていますが、武器インターフェイスをエクスポートします。甘い、今、私たちは確かに世界を破壊することができます。それはちょっとした一見のように思えますが、それは物事を機能させます。


ブリッジパターンは前もって実装するものです-直交する2つの階層があることがわかっている場合は、非常識な番号を取得しないようにインターフェイスと実装を分離する方法を提供しますクラスの。あなたが持っているとしましょう:

MemoryMappedFileおよびDirectReadFileタイプのファイルオブジェクト。さまざまなソース(たぶんLinuxとWindowsの実装など)からファイルを読みたいとしましょう。 Bridgeを使用すると、次のことを回避できます。

MemoryMappedWindowsFile MemoryMappedLinuxFile DirectReadWindowsFile DirectReadLinuxFile

156
James

http://en.wikipedia.org/wiki/Adapter_pattern

アダプタパターンは、既存のコードを新しいシステムまたはインターフェイスで動作させることに関するものです。

別のアプリケーションの既存の拡張性インターフェースに提供したい会社標準のWebサービスAPIのセットがある場合、これを行うためのアダプターのセットを作成することを検討できます。灰色の領域があり、これはファサードのような他のパターンも似ているため、パターンを技術的に定義する方法に関するものです。

http://en.wikipedia.org/wiki/Bridge_pattern

ブリッジパターンを使用すると、アルゴリズムまたはシステムの代替実装を可能にすることができます。

古典的なブリッジパターンの例ではありませんが、データストアの実装がいくつかある場合を想像してください。1つはスペースで効率的であり、もう1つは生のパフォーマンスで効率的です... 。

「どのパターンをどこで使用できるか」という質問に関しては、プロジェクトにとって意味のあるところならどこでも、答えが返ってきます。おそらく、どちらを使用する必要があると思われるのかについての議論を導くために、説明の編集を提供することを検討してください。

13
Jeff Wilcox

Adapter:

  1. 構造的なパターンです
  2. 互換性のない2つのインターフェイスを使用すると便利です。

UML図:from dofactory article:

enter image description here

Target:クライアントが使用するドメイン固有のインターフェースを定義します。

Adapter:インターフェイスAdapteeをターゲットインターフェイスに適合させます。

Adaptee:適応が必要な既存のインターフェースを定義します。

Client:Targetインターフェースに準拠するオブジェクトと連携します。

例:

SquareとRectangleは2つの異なる形状であり、それぞれのarea()を取得するには異なる方法が必要です。ただし、Squareは、いくつかのプロパティを変換することで、Rectangleインターフェイスで動作します。

public class AdapterDemo{
    public static void main(String args[]){
        SquareArea s = new SquareArea(4);
        System.out.println("Square area :"+s.getArea());
    }
}

class RectangleArea {
    public int getArea(int length, int width){
        return length * width;
    }
}

class SquareArea extends RectangleArea {

    int length;
    public SquareArea(int length){
        this.length = length;
    }
    public int getArea(){
        return getArea(length,length);
    }
}

ブリッジ:

  1. 構造パターンです
  2. それは実装から抽象化を切り離し、両方が独立して変化する可能性があります
  3. コンポジションが継承の代わりに使用されているため可能です

EDIT:(@quasoftの提案による)

このパターンには4つのコンポーネントがあります。

  1. Abstraction:インターフェイスを定義します

  2. RefinedAbstraction:抽象化を実装します:

  3. Implementor:実装用のインターフェースを定義します

  4. ConcreteImplementor:Implementorインターフェイスを実装します。

コードスニペット:

Gear gear = new ManualGear();
Vehicle vehicle = new Car(gear);
vehicle.addGear();

gear = new AutoGear();
vehicle = new Car(gear);
vehicle.addGear();

関連記事:

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

主な違い:from sourcemaking article

  1. アダプタは、設計後に物事を機能させます。 Bridgeは、それらが機能する前に機能します。
  2. Bridgeは、抽象化と実装が独立して異なるように事前に設計されています。アダプターは、関係のないクラスが連携して動作するように改良されています。
10
Ravindra babu

この投稿はかなり前からありました。ただし、ファサードはアダプターに多少似ていますが、まったく同じものではないことを理解することが重要です。アダプタは、既存のクラスを通常は互換性のないクライアントクラスに「適合」させます。アプリケーションがクライアントとして使用している古いワークフローシステムがあるとします。あなたの会社は、ワークフローシステムを新しい「互換性のない」ものに置き換える可能性があります(インターフェイスに関して)。ほとんどの場合、アダプターパターンを使用して、新しいワークフローエンジンのインターフェイスを実際に呼び出すコードを作成できます。ブリッジは通常、別の方法で使用されます。異なるファイルシステム(ローカルディスク、NFSなど)で動作する必要があるシステムが実際にある場合は、ブリッジパターンを使用して、すべてのファイルシステムで動作する抽象化レイヤーを1つ作成できます。これは基本的に、ブリッジパターンの単純な使用例です。ファサードとアダプターはいくつかのプロパティを共有しますが、ファサードは通常、既存のインターフェース/クラスを簡素化するために使用されます。 EJBの初期には、EJBのローカル呼び出しはありませんでした。開発者は常にスタブを取得し、それを絞り込んで「擬似リモート」と呼びました。これはしばしばパフォーマンスの問題を引き起こしました(特に実際にネットワーク経由で呼び出された場合)。経験豊富な開発者は、ファサードパターンを使用して、非常に粗いインターフェイスをクライアントに提供します。次に、このファサードは、より詳細な異なるメソッドを複数回呼び出します。全体として、これにより、必要なメソッド呼び出しの数が大幅に削減され、パフォーマンスが向上しました。

8
John Penner

ブリッジは改良されたアダプターです。ブリッジにはアダプターが含まれており、柔軟性が追加されています。 Ravindraの回答の要素がパターン間でどのようにマッピングされるかを次に示します。

      Adapter  |    Bridge
    -----------|---------------
    Target     | Abstraction
    -----------|---------------
               | RefinedAbstraction
               |
               |   This element is Bridge specific. If there is a group of 
               |   implementations that share the same logic, the logic can be placed here.
               |   For example, all cars split into two large groups: manual and auto. 
               |   So, there will be two RefinedAbstraction classes.
    -----------|--------------- 
    Adapter    | Implementor
    -----------|---------------
    Adaptee    | ConcreteImplementor
0
polina-c

(ジェネリック/抽象化された)描画機能と、Shapeを実装するCircleを持つ抽象Shapeクラスがあるとします。ブリッジパターンは、単純に、実装(Circleでの描画)と汎用/抽象化された機能(Shapeクラスでの描画)を分離する双方向の抽象化アプローチです。

それは本当にどういう意味ですか?一見したところ、すでに依存関係の反転によって作成されているように聞こえます。そのため、より低リジッドな、またはよりモジュラーなコードベースを持つ心配はありません。しかし、それはその背後にある少し深い哲学です。

私の理解から、現在のシステム(RedCircleやGreenCircleなど)と密接に関連し、単一の機能(colorなど)だけが異なる新しいクラスを追加する必要がある場合、使用パターンの必要性が浮かぶかもしれません。また、既存のシステムクラス(CircleまたはShape)を頻繁に変更し、新しく追加したクラスがこれらの変更の影響を受けないようにする場合は、特にBridgeパターンが必要になります。そのため、一般的な描画機能が抽象化されて新しいインターフェイスになり、ShapeやCircleから独立して描画動作を変更できるようになりました。

0
stdout