[design-patterns] Bridge Pattern은 언제 사용합니까? 어댑터 패턴과 어떻게 다릅니 까?

실제 응용 프로그램에서 Bridge Pattern 을 사용한 적이 있습니까? 그렇다면 어떻게 사용 했습니까? 나입니까, 아니면 약간의 의존성 주입이 혼합 된 어댑터 패턴입니까? 정말 자체 패턴을 가질 가치가 있습니까?



답변

Bridge 패턴의 전형적인 예는 UI 환경에서 모양을 정의하는 데 사용됩니다 ( Bridge pattern Wikipedia 항목 참조 ). Bridge 패턴은 템플릿전략 패턴 의 합성물 입니다 .

브리지 패턴에서 어댑터 패턴의 몇 가지 측면을 공통적으로 볼 수 있습니다. 그러나이 기사 에서 인용하면 다음과 같습니다.

언뜻보기에 Bridge 패턴은 클래스가 한 종류의 인터페이스를 다른 종류로 변환하는 데 사용된다는 점에서 Adapter 패턴과 매우 유사합니다. 그러나 어댑터 패턴의 목적은 하나 이상의 클래스의 인터페이스를 특정 클래스의 인터페이스와 동일하게 만드는 것입니다. Bridge 패턴은 구현에서 클래스의 인터페이스를 분리하도록 설계되었으므로 클라이언트 코드를 변경하지 않고도 구현을 변경하거나 대체 할 수 있습니다.


답변

FedericoJohn의 답변 이 조합되어 있습니다.

언제:

                   ----Shape---
                  /            \
         Rectangle              Circle
        /         \            /      \
BlueRectangle  RedRectangle BlueCircle RedCircle

리팩터링 :

          ----Shape---                        Color
         /            \                       /   \
Rectangle(Color)   Circle(Color)           Blue   Red


답변

Bridge 패턴은 “상속보다 컴포지션 선호”라는 오래된 조언을 적용한 것입니다. 서로 직교하는 방식으로 서로 다른 시간을 하위 클래스 화해야 할 때 편리합니다. 컬러 모양의 계층을 구현해야한다고 가정 해 보겠습니다. Rectangle과 Circle을 사용하여 Shape를 하위 클래스로 분류 한 다음 RedRectangle, BlueRectangle 및 GreenRectangle을 사용하여 Rectangle을 하위 클래스로 만들고 Circle에 대해서도 동일하게 하위 클래스를 만들지 않겠습니까? 각 모양 에는 색상 있고 색상 계층 구조를 구현하는 것이 좋습니다. 이것이 바로 브릿지 패턴입니다. 글쎄요, 저는 “색상 계층 구조”를 구현하지 않겠지 만 당신은 아이디어를 얻었습니다.


답변

언제:

        A
     /     \
    Aa      Ab
   / \     /  \
 Aa1 Aa2  Ab1 Ab2

리팩터링 :

     A         N
  /     \     / \
Aa(N) Ab(N)  1   2


답변

어댑터와 브리지는 확실히 관련이 있으며 그 차이는 미묘합니다. 이러한 패턴 중 하나를 사용하고 있다고 생각하는 일부 사람들은 실제로 다른 패턴을 사용하고있을 가능성이 있습니다.

내가 본 설명은 이미 존재 하는 일부 호환되지 않는 클래스의 인터페이스를 통합하려고 할 때 Adapter가 사용된다는 것 입니다. 어댑터는 레거시 로 간주 될 수있는 구현에 대한 일종의 변환기 역할을합니다 .

브리지 패턴은 그린 필드 일 가능성이 더 높은 코드에 사용됩니다. 변경해야하는 구현에 대한 추상 인터페이스를 제공하기 위해 Bridge를 디자인하고 있지만 해당 구현 클래스의 인터페이스도 정의합니다.

장치 드라이버는 Bridge의 자주 인용되는 예이지만 장치 공급 업체에 대한 인터페이스 사양을 정의하는 경우 Bridge라고 말하고 싶지만 기존 장치 드라이버를 가져 와서 래퍼 클래스를 만드는 경우 어댑터입니다. 통합 인터페이스를 제공합니다.

따라서 코드 측면에서 두 패턴은 매우 유사합니다. 비즈니스 측면에서는 다릅니다.

http://c2.com/cgi/wiki?BridgePattern 참조


답변

내 경험상 Bridge는 도메인에 두 개의 직교 차원이있을 때마다 솔루션이기 때문에 꽤 자주 반복되는 패턴 입니다. 예 : 모양 및 그리기 방법, 동작 및 플랫폼, 파일 형식 및 직렬 변환기 등.

그리고 조언 : 항상 구현 관점이 아닌 개념적 관점에서 디자인 패턴 생각 하십시오. 올바른 관점에서 보면 Bridge는 다른 문제를 해결하기 때문에 Adapter와 혼동 할 수 없으며, 구성은 자체 때문이 아니라 직교 문제를 개별적으로 처리 할 수 ​​있기 때문에 상속보다 우수합니다.


답변

BridgeAdapter 의 의도 는 다르며 두 패턴이 별도로 필요합니다.

브리지 패턴 :

  1. 구조적 패턴입니다.
  2. 추상화 및 구현은 컴파일 타임에 바인딩되지 않습니다.
  3. 추상화 및 구현-둘 다 클라이언트에 영향을주지 않고 달라질 수 있습니다.
  4. 상속보다 구성을 사용합니다.

다음과 같은 경우 브리지 패턴을 사용합니다.

  1. 구현의 런타임 바인딩을 원합니다.
  2. 결합 된 인터페이스와 수많은 구현으로 인해 클래스가 급증하고 있습니다.
  3. 여러 개체간에 구현을 공유하려는 경우
  4. 직교 클래스 계층 구조를 매핑해야합니다.

@ John Sonmez 답변은 클래스 계층 구조를 줄이는 데 브리지 패턴의 효과를 명확하게 보여줍니다.

아래 문서 링크를 참조하여 코드 예제로 브리지 패턴에 대한 더 나은 통찰력을 얻을 수 있습니다.

어댑터 패턴 :

  1. 작업 함께 두 관련이없는 인터페이스를 허용 가능한 같은 역할을하고, 다른 객체를 통해.
  2. 원래 인터페이스를 수정합니다.

주요 차이점 :

  1. 어댑터 는 설계된 후에 작동합니다. Bridge 는 그들이 존재하기 전에 작동하도록합니다.
  2. Bridge추상화와 구현이 독립적으로 변경 될 수 있도록 미리 설계되었습니다 . 어댑터 는 관련없는 클래스가 함께 작동하도록 개조되었습니다.
  3. 의도 : 어댑터를 사용하면 관련되지 않은 두 인터페이스가 함께 작동 할 수 있습니다. Bridge를 사용하면 추상화 및 구현이 독립적으로 달라질 수 있습니다.

UML 다이어그램 및 작업 코드와 관련된 SE 질문 :

브리지 패턴과 어댑터 패턴의 차이점

유용한 기사 :

sourcemaking 브리지 패턴 기사

sourcemaking 어댑터 패턴 기사

journaldev 브리지 패턴 기사

편집하다:

Bridge Pattern 실제 사례

브리지 패턴은 구현에서 추상화를 분리하여 둘 다 독립적으로 달라질 수 있습니다. 그것은 상속이 아닌 구성으로 달성되었습니다.

Wikipedia의 브리지 패턴 UML :

Wikipedia의 브리지 패턴 UML

이 패턴에는 네 가지 구성 요소가 있습니다.

Abstraction: 인터페이스를 정의합니다.

RefinedAbstraction: 추상화를 구현합니다.

Implementor: 구현을위한 인터페이스를 정의합니다.

ConcreteImplementor: Implementor 인터페이스를 구현합니다.

The crux of Bridge pattern :컴포지션을 사용하는 두 개의 직교 클래스 계층 (상속 없음). 추상화 계층 및 구현 계층은 독립적으로 다를 수 있습니다. 구현은 추상화를 참조하지 않습니다. 추상화에는 구성을 통해 구현 인터페이스가 구성원으로 포함됩니다. 이 구성은 상속 계층의 수준을 한 단계 더 줄입니다.

실제 단어 사용 사례 :

다른 차량이 수동 및 자동 기어 시스템의 두 버전을 모두 갖도록합니다.

예제 코드 :

/* Implementor interface*/
interface Gear{
    void handleGear();
}

/* Concrete Implementor - 1 */
class ManualGear implements Gear{
    public void handleGear(){
        System.out.println("Manual gear");
    }
}
/* Concrete Implementor - 2 */
class AutoGear implements Gear{
    public void handleGear(){
        System.out.println("Auto gear");
    }
}
/* Abstraction (abstract class) */
abstract class Vehicle {
    Gear gear;
    public Vehicle(Gear gear){
        this.gear = gear;
    }
    abstract void addGear();
}
/* RefinedAbstraction - 1*/
class Car extends Vehicle{
    public Car(Gear gear){
        super(gear);
        // initialize various other Car components to make the car
    }
    public void addGear(){
        System.out.print("Car handles ");
        gear.handleGear();
    }
}
/* RefinedAbstraction - 2 */
class Truck extends Vehicle{
    public Truck(Gear gear){
        super(gear);
        // initialize various other Truck components to make the car
    }
    public void addGear(){
        System.out.print("Truck handles " );
        gear.handleGear();
    }
}
/* Client program */
public class BridgeDemo {
    public static void main(String args[]){
        Gear gear = new ManualGear();
        Vehicle vehicle = new Car(gear);
        vehicle.addGear();

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

        gear = new ManualGear();
        vehicle = new Truck(gear);
        vehicle.addGear();

        gear = new AutoGear();
        vehicle = new Truck(gear);
        vehicle.addGear();
    }
}

산출:

Car handles Manual gear
Car handles Auto gear
Truck handles Manual gear
Truck handles Auto gear

설명:

  1. Vehicle 추상화입니다.
  2. CarTruck두 가지 구체적인 구현입니다 Vehicle.
  3. Vehicle추상적 인 방법을 정의합니다 : addGear().
  4. Gear 구현 자 인터페이스
  5. ManualGear그리고 AutoGear두 가지 구현입니다 Gear
  6. Vehicleimplementor인터페이스를 구현하는 대신 인터페이스를 포함 합니다. Compositon구현 자 인터페이스의 핵심은이 패턴의 핵심입니다. 추상화와 구현이 독립적으로 달라질 수 있습니다.
  7. CarTruck추상화를위한 구현 (재정의 된 추상화)을 정의합니다. addGear(): : 포함 Gear-둘 중 하나 Manual또는Auto

브리지 패턴의 사용 사례 :

  1. 추상화구현 은 서로 독립적으로 변경 될 수 있으며 컴파일 타임에 바인딩되지 않습니다.
  2. 직교 계층 구조 매핑-하나는 추상화 용 이고 다른 하나는 구현 용 입니다.