JAVA/JAVA Design Pattern

JAVA 브리지(Bridge) 패턴

임베디드 친구 2024. 12. 28. 10:30
반응형

브리지 패턴은 구현(Implementation)인터페이스(Abstraction)를 분리하여 독립적으로 확장할 수 있도록 도와주는 디자인 패턴입니다. 이를 통해 하나의 클래스 계층 구조를 복잡하게 만들지 않고도 다형성추상화 계층을 유연하게 적용할 수 있습니다.

이 포스팅에서는 브리지 패턴의 핵심 개념과 실제 사용 사례를 알아보고, 클래스 다이어그램과 예제 코드를 통해 이를 이해해보겠습니다.


브리지 패턴이란?

브리지 패턴은 두 개의 독립적인 계층을 나누어 추상화(Abstraction) 부분과 구현(Implementation) 부분이 서로 독립적으로 확장될 수 있도록 구조를 설계하는 패턴입니다.

핵심 포인트

  1. 인터페이스구현을 분리한다.
  2. 두 부분이 독립적으로 확장 가능하다.
  3. 클라이언트 코드는 추상화 계층을 통해서만 구현을 사용한다.

클래스 다이어그램

아래는 브리지 패턴의 클래스 다이어그램입니다.

                +--------------------+
                |   Abstraction      |
                +--------------------+
                | - device: Device   |
                |                    |
                |    operation()     |
                +--------------------+
                          |
                          |
                +--------------------+
                | RefinedAbstraction |
                +--------------------+
                |                    |
                | operation()        |
                +--------------------+
                          |
                +--------------------+
                |   Implementor      |<---------+
                +--------------------+          |
                |  operationImpl()   |          |
                +--------------------+          |
                          |                     |
                +------------------+   +------------------+
                | ConcreteImplA    |   | ConcreteImplB    |
                +------------------+   +------------------+
                | operationImpl()  |   | operationImpl()  |
                +------------------+   +------------------+
  1. Abstraction: 추상화된 인터페이스를 정의합니다. 구현(Implementor)에 대한 참조를 가집니다.
  2. RefinedAbstraction: Abstraction의 확장 클래스입니다.
  3. Implementor: 구현을 위한 인터페이스입니다.
  4. ConcreteImplementor: Implementor의 구체적인 구현 클래스입니다.

예제 코드

아래는 브리지 패턴을 적용한 예제 코드입니다. 기기(Device)리모컨(Remote)을 분리하여 서로 독립적으로 확장할 수 있는 구조를 설계해보겠습니다.

Java 코드

// Implementor: Device 인터페이스
interface Device {
    void turnOn();
    void turnOff();
    void setVolume(int volume);
}

// ConcreteImplementorA: TV 클래스
class TV implements Device {
    private int volume;

    @Override
    public void turnOn() {
        System.out.println("TV is ON");
    }

    @Override
    public void turnOff() {
        System.out.println("TV is OFF");
    }

    @Override
    public void setVolume(int volume) {
        this.volume = volume;
        System.out.println("TV volume set to " + volume);
    }
}

// ConcreteImplementorB: Radio 클래스
class Radio implements Device {
    private int volume;

    @Override
    public void turnOn() {
        System.out.println("Radio is ON");
    }

    @Override
    public void turnOff() {
        System.out.println("Radio is OFF");
    }

    @Override
    public void setVolume(int volume) {
        this.volume = volume;
        System.out.println("Radio volume set to " + volume);
    }
}

// Abstraction: RemoteControl 추상화 클래스
abstract class RemoteControl {
    protected Device device;

    public RemoteControl(Device device) {
        this.device = device;
    }

    public abstract void turnOn();
    public abstract void turnOff();
    public abstract void setVolume(int volume);
}

// RefinedAbstraction: AdvancedRemoteControl
class AdvancedRemoteControl extends RemoteControl {
    public AdvancedRemoteControl(Device device) {
        super(device);
    }

    @Override
    public void turnOn() {
        device.turnOn();
    }

    @Override
    public void turnOff() {
        device.turnOff();
    }

    @Override
    public void setVolume(int volume) {
        device.setVolume(volume);
    }

    public void mute() {
        System.out.println("Muting the device");
        device.setVolume(0);
    }
}

// 클라이언트 코드
public class BridgePatternExample {
    public static void main(String[] args) {
        Device tv = new TV();
        Device radio = new Radio();

        RemoteControl tvRemote = new AdvancedRemoteControl(tv);
        RemoteControl radioRemote = new AdvancedRemoteControl(radio);

        tvRemote.turnOn();
        tvRemote.setVolume(20);
        tvRemote.turnOff();

        System.out.println("-----------------");

        radioRemote.turnOn();
        radioRemote.setVolume(10);
        ((AdvancedRemoteControl) radioRemote).mute();
        radioRemote.turnOff();
    }
}

출력 결과

TV is ON
TV volume set to 20
TV is OFF
-----------------
Radio is ON
Radio volume set to 10
Muting the device
Radio volume set to 0
Radio is OFF

실제 사용 사례

브리지 패턴은 다음과 같은 상황에서 유용하게 사용됩니다:

  1. 디바이스와 리모컨: 다양한 종류의 디바이스(TV, 라디오 등)를 동일한 인터페이스(RemoteControl)를 통해 제어할 수 있도록 확장할 때.
  2. UI 플랫폼 독립성: 플랫폼에 종속되지 않도록 UI를 추상화하고 실제 구현을 플랫폼에 맞게 설계할 때.
  3. 데이터베이스 연결: 데이터베이스 접근 레이어에서 SQL과 NoSQL을 추상화하여 유연하게 구현을 확장할 때.

결론

브리지 패턴은 추상화와 구현을 분리하여 두 부분이 독립적으로 확장될 수 있도록 설계하는 강력한 디자인 패턴입니다. 이를 통해 유지보수성확장성을 높일 수 있습니다.

이 포스팅에서는 간단한 디바이스 제어 예제를 통해 브리지 패턴의 핵심 개념을 설명했습니다. 다양한 실제 사용 사례를 고려하며 브리지 패턴을 프로젝트에 적용해보세요!

반응형