Design Pattern | Bridge Pattern (브릿지 패턴)

Bridge 패턴이란?

  • Bridge라는 영어 단어는 다리라는 의미이다.
  • 현실 세계의 다리가 강가를 양쪽으로 연결시키는 것처럼, Bridge 패턴도 2개의 장소를 연결하는 방식이다.
  • 구현과 추상을 분리. ‘기능 클래스 계층’과 ‘구현 클래스 계층’간에 다리(Bridge)를 놓는 역할을 하는 패턴이다.
  • Bridge 패턴이 교차하는 두 위치는 기능 클래스 계층구현 클래스 계층이 된다.
    • 기능 클래스의 계층 : 슈퍼 클래스로 기본적인 기능을 가지고 있어, 서브 클래스로 새로운 기능을 추가하는 경우의 계층이다.
    • 구현 클래스의 계층 : 슈퍼 클래스로 추상 메소드에 의해 인터페이스를 규정하고 있어, 서브 클래스에서 구상 메소드에 의해 그 인터페이스를 구현하는 경우의 계층이다.
  • GoF의 디자인 패턴에서는 구조와 관련된 디자인 패턴으로 분류된다.

Bridge 패턴 예제 프로그램

입력한 문자열을 지정 횟수 및 랜덤 횟수 표시하는 예제 프로그램이다.

Class Diagram
Bridge Pattern

1. Display 클래스

기능 클래스 계층이 되는 “표시"를 실시하는 클래스이다. 이 클래스가 가지는 impl 필드가 2개의 클래스 계층의 “다리"가 된다.

Display.java

package com.devkuma.designpattern.structural.bridge;

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();
    }
}

2. CountDisplay 클래스

기능 클래스 계층이 되는 “지정 횟수 표시"라고 하는 기능을 추가한 클래스이다.

CountDisplay.java

package com.devkuma.designpattern.structural.bridge;

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();
    }
}

3. RandomCountDisplay 클래스

기능 클래스 계층이 되는 “랜덤 횟수 표시"라는 기능을 추가한 클래스이다.

RandomCountDisplay.java

package com.devkuma.designpattern.structural.bridge;

import java.util.Random;

public class RandomCountDisplay extends CountDisplay {

    private Random random = new Random();

    public RandomCountDisplay(DisplayImpl impl) {
        super(impl);
    }

    public void randomDisplay(int times) {
        multiDisplay(random.nextInt(times));
    }
}

4. DisplayImpl 클래스

구현 클래스 계층이 되는 “표시"용의 메소드를 정의한 클래스이다.

DisplayImpl.java

public abstract class DisplayImpl {
    public abstract void rawOpen();
    public abstract void rawPrint();
    public abstract void rawClose();
}

5. StringDisplayImpl 클래스

구현 클래스 계층이 되는 “문자열을 사용해 표시"하는 클래스이다.

StringDisplayImpl.java

package com.devkuma.designpattern.structural.bridge;

public class StringDisplayImpl extends DisplayImpl {

    private String string;
    private int width;

    public StringDisplayImpl(String string) {
        this.string = string;
        this.width = string.getBytes().length;
    }

    public void rawOpen() {
        printLine();
    }

    public void rawPrint() {
        System.out.println("|" + string + "|");
    }

    public void rawClose() {
        printLine();
    }

    private void printLine() {
        System.out.print("+");
        for (int i = 0; i < width; i++) {
            System.out.print("-");
        }
        System.out.println("+");
    }
}

6. Main 클래스

메인 처리를 실행하는 클래스이다.

Main.java

package com.devkuma.designpattern.structural.bridge;

public class Main {

    public static void main(String[] args) {
        Display display = new Display(new StringDisplayImpl("Display Test"));
        CountDisplay countDisplay = new CountDisplay(new StringDisplayImpl("CountDisplay Test"));
        RandomCountDisplay randomCountDisplay = new RandomCountDisplay(new StringDisplayImpl("RandomCountDisplay Test"));
        display.display();
        countDisplay.multiDisplay(5);
        randomCountDisplay.randomDisplay(10);
    }
}

7. 실행 결과

+------------+
|Display Test|
+------------+
+-----------------+
|CountDisplay Test|
|CountDisplay Test|
|CountDisplay Test|
|CountDisplay Test|
|CountDisplay Test|
+-----------------+
+-----------------------+
|RandomCountDisplay Test|
|RandomCountDisplay Test|
|RandomCountDisplay Test|
|RandomCountDisplay Test|
|RandomCountDisplay Test|
|RandomCountDisplay Test|
+-----------------------+

장점

앞서 언급했듯이 브릿지 패턴의 특징은 기능 클래스의 계층구현 클래스의 계층을 구분한다는 것이다. 이 2개의 클래스 계층을 나누어 두면, 각각의 클래스 계층을 독립적으로 확장할 수 있다.
기능을 추가하려면 함수의 클래스 계층에 클래스를 추가한다. 이 때, 구현 클래스 계층은 전혀 수정할 필요는 없다. 게다가, 추가한 기능은 모든 구현으로 이용할 수 있게 된다.
예제 프로그램에서는, CountDisplay 클래스나 RandomCountDisplay 클래스를 추가하는 것이 기능 추가에 해당한다.
이와 같이 Bridge 패턴에서는 클래스의 확장을 전망하고 잘 할 수 있다.