Bridge Pattern

개념
- 구현 뿐만 아니라 추상화된 부분가지 변경시켜야 하는 경우 사용

I. 의도

    구현과 추상화 개념을 분리하는 것

   정의 : 기능의 클래스 계층과 구현의 클래스 계층을 분리하는 패턴
          : 구현 뿐만 아니라 추상화된 부분가지 변경시켜야 하는 경우 사용

II. 활용

  • 추상화 개념과 이에 대한 구현간의 종속성을 없애고 싶거나, 또는 런타임시 구현 방법을 선택하거나 구현 내용을 변경하고 싶을 경우
  • 추상화 개념과 구현 모두가 독립적으로 상속에 의해 확장 가능할 경우
  • 추상화 개념에 대한 구현 내용을 변경하는 것은 다른 관련 프로그램에 아무 영향 없다. 추상화 개념에 해당하는 클래스를 사용하는 코드들은 구현 클래스가 변경되었다고 해서 다시 컴파일될 필요 없다
  • 클라이언트로 부터 구현을 은닉하길 원할 때
  • 클래스 계층도에서 클래스 수가 급증하는 것을 방지하고자 할 때
  • 여러 객체들에 걸쳐 구현을 공유할 때 또는 이런 사실을 다른 코드에 공개하고 싶지 않을 때

III. 결과

  • 인터페이스와 구현의 결합도 약화
  • 확장성 제고 – abstraction과 implementor를 독립적으로 확장
  • 구현 사항 은닉

관련 패턴: Abstract Factory 패턴을 이용해서 특정 Bridge를 생성하고 합성할 수 있도록 한다.

Adapter 패턴을 이용해서 서로 관련없는 클래스들을 연결할 수도 있다. 이는 이미 설계가 끝난 클래스와 통합을 해야 하는 경우에 필요하다.

 

참여객체

역할

Abstraction

-기능 클래스 계층의 최상위에 있는 클래스

-Implementor 의 메소드를 사용해서 기본적인 기능만을 제공하는 클래스

-예제 : Display 클래스가 해당됨

RefinedAbstraction

-Abstraction에 기능을 추가(확장)역할

-예제 : CountDisplay 클래스가 해당됨

Implementor

-구현 클래스 계층의 최상위에 있는 클래스

-Abstraction 역할의 인터페이스를 구현하기 위한 메소드를 규정하는 역할

-예제 : DisplayImpl 클래스가 해당됨

ConcreteImplementor

-Implementor 역할의 인터페이스를 구체적으로 구현하는 역할

-예제 : WinImpl, MacImpl클래스가 해당됨

 

<예제> Bridge Pattern 코드

가. Class Diagram

 

나. Abstraction

public class Display {

    private DisplayImpl impl;

    public Display(DisplayImpl impl) {

        this.impl = impl;

    }  

    public void open() {

        impl.rawOpen();

    }

    public void print() {

        impl.rawPrint();

    }

    public void close() {

        impl.rawClose();

    }

    public final void display() {

        open();

        print();

        close();

    }

}

 

다. RefinedAbstaction

public class CountDisplay extends Display {  

    public CountDisplay(DisplayImpl impl) {

        super(impl);

    }

    public void multiDisplay(int times) {

        open();

        for (int i = 0; i < times; i++) {

            print();

        }

        close();

    }

}

 

 

라. Implementor

public interface DisplayImpl {

    void rawOpen();

    void rawPrint();

    void rawClose();

}

마. Concrete Implementor

public class StringDisplayImpl implements DisplayImpl {

    private String str;

    private int width;

  

    public StringDisplayImpl(String str) {

        this.str = str;

        this.width = str.getBytes().length;

    }

    @Override

    public void rawOpen() {

        printLine();

    }

    @Override

    public void rawPrint() {

        System.out.println("|" + str + "|");

    }

    @Override

    public void rawClose() {

        printLine();

    }

    private void printLine() {

        System.out.print("+");

        for (int i = 0; i <width; i++) {

            System.out.print("-");

        }

        System.out.println("+");

    }

}

바. Main

public class Main {

  public static void main(String[] args) {

    Display d1 = new Display(new StringDisplayImpl("Hello, Korea."));

    Display d2 = new CountDisplay(new StringDisplayImpl("Hello, World."));

    CountDisplay d3 = new CountDisplay(new StringDisplayImpl("Hellow, Universe."));

   

    d1.display();

    d2.display();

    d3.display();

    d3.multiDisplay(5);

  }

}

댓글