구조 - 브릿지 패턴(Bridge Pattern)


이미지 출처 : https://refactoring.guru/ko/design-patterns/bridge


🖥️ 브릿지 패턴(Bridge Pattern)이란?

추상화와 구현을 분리하여 독립적으로 변형할 수 있도록 하는 구조적 디자인 패턴.
이는 하나의 계층을 변경해도 다른 계층에 영향을 주지 않도록 설계하여 유연성을 극대화함.


🖥️ 브릿지 패턴을 사용하는 이유


💥 상속을 통한 기능 확장의 문제점

  1. 추상화(Abstraction)와 구현(Implementation)이 강하게 결합되면 확장성이 떨어짐.
  2. 새로운 기능을 추가할 때 기존 클래스를 수정해야 하는 문제 발생.
  3. 유지보수와 코드 재사용이 어려워짐.


ex) 그래픽 시스템에서 다양한 도형과 렌더링 방식이 존재하는 경우

조합필요 클래스
원형 + API1CircleWithAPI1
원형 + API2CircleWithAPI2
사각형 + API1RectangleWithAPI1
사각형 + API2RectangleWithAPI2
원형 + API3CircleWithAPI3
사각형 + API3RectangleWithAPI3
새로운 도형 추가 시모든 API 조합 클래스를 추가해야 함

✅ 해결방안
위처럼 상속 기반의 확장 문제를 해결하기 위해 브릿지 패턴을 사용.

브릿지 패턴은 추상화 계층과 구현 계층을 분리하여 독립적으로 확장 가능.
기존 코드 수정 없이 새로운 기능을 추가할 수 있음.


🖥️ 브릿지 패턴의 구성 요소

구성 요소설명
Abstraction (추상화)상위 수준의 제어를 담당하며, Implementor 객체에 작업을 위임.
RefinedAbstraction (정제된 추상화)Abstraction의 확장으로, 구체적인 기능을 추가하는 클래스.
Implementor (구현자)Abstraction이 사용하는 인터페이스를 정의.
ConcreteImplementor (구체적인 구현자)Implementor 인터페이스를 실제로 구현하는 클래스.

🖥️ 브릿지 패턴(Bridge Pattern) 예시 코드

C++ 예시

#include <stdio.h>

//구현을 위한 인터페이스 정의 - * Implementor (구현자)
class DrawingAPI 
{
public:
    virtual void drawCircle(double x, double y, double radius) = 0;
    virtual ~DrawingAPI() {}
};

//구현 클래스 1 - * ConcreteImplementor (구체적인 구현자)
class DrawingAPI1 : public DrawingAPI 
{
public:
    void drawCircle(double x, double y, double radius) override 
    {
        printf("API1.circle at (%.1f, %.1f) radius %.1f\n", x, y, radius);
    }
};

//구현 클래스 2 - * ConcreteImplementor (구체적인 구현자)
class DrawingAPI2 : public DrawingAPI 
{
public:
    void drawCircle(double x, double y, double radius) override 
    {
        printf("API2.circle at (%.1f, %.1f) radius %.1f\n", x, y, radius);
    }
};

//도형의 추상 클래스 - * Abstraction (추상화)
class Shape 
{
protected:
    DrawingAPI* drawingAPI;

public:
    Shape(DrawingAPI* api) : drawingAPI(api) {}
    virtual void draw() = 0;
    virtual void resizeByPercentage(double pct) = 0;
    virtual ~Shape() {}
};

//원형 도형 클래스 - * Refined Abstraction (정제된 추상화)
class CircleShape : public Shape 
{
private:
    double x, y, radius;

public:
    CircleShape(double x, double y, double radius, DrawingAPI* api)
        : Shape(api), x(x), y(y), radius(radius) {}

    void draw() override 
    {
        drawingAPI->drawCircle(x, y, radius);
    }

    void resizeByPercentage(double pct) override 
    {
        radius *= pct;
    }
};

int main() 
{
    //원 객체 생성
    Shape* circle1 = new CircleShape(1, 2, 3, new DrawingAPI1());
    Shape* circle2 = new CircleShape(5, 7, 11, new DrawingAPI2());

    //도형 그리기
    circle1->draw();
    circle2->draw();

    //최종 객체들 삭제 - 메모리 릭 방지
    delete circle1;
    delete circle2;

    return 0;
}

출력 결과

API1.circle at (1.0, 2.0) radius 3.0
API2.circle at (5.0, 7.0) radius 11.0

설명

  • Shape 클래스는 DrawingAPI를 활용하여 도형을 그리는 역할을 수행.
  • CircleShapeShape를 상속받아 원형을 구현하며, DrawingAPI 객체를 통해 실제 그림을 그림.
  • main()에서 CircleShape를 생성하여 다양한 구현(API1, API2)과 독립적으로 결합 가능.
  • 새로운 DrawingAPI 추가 시 기존 Shape 클래스를 수정할 필요 없음.

출처 :
* https://en.wikipedia.org/wiki/Bridge_pattern
* https://refactoring.guru/ko/design-patterns/bridge


© 2024. All rights reserved.

Powered by Hydejack v9.2.1