브릿지(Bridge) 패턴

2024. 10. 17. 00:37Design Pattern

Bridge 패턴 - 개념과 구현

Bridge 패턴구조 패턴(Structural Pattern) 중 하나로, 구현부와 추상화부를 분리하여 둘을 독립적으로 변화시킬 수 있도록 하는 패턴입니다. 이 패턴은 여러 가지 방식으로 구성을 변경할 수 있는 상황에서 특히 유용합니다. 즉, 클라이언트가 사용하고자 하는 기능과 그 기능의 구현을 독립적으로 발전시킬 수 있는 방법을 제공합니다.


1. Bridge 패턴이란?

Bridge 패턴은 추상화(Abstraction)구현(Implementation)을 분리하여 각각을 독립적으로 발전시킬 수 있도록 설계된 구조입니다. 이 패턴을 사용하면 추상화와 그 구현을 서로 독립적으로 확장할 수 있어, 코드의 유연성과 재사용성을 높일 수 있습니다.

언제 사용하는가?

  • 다양한 구현 방식이 필요하지만, 각 구현 방식이 독립적으로 변할 수 있는 상황에서.
  • 여러 기능이 동시에 존재하며, 각각의 기능에 대한 변경이 빈번한 경우.
  • 클래스의 수가 너무 많아지는 것을 방지하고, 코드의 복잡성을 줄이고 싶을 때.

2. Bridge 패턴의 구조

Bridge 패턴은 크게 Abstraction, RefinedAbstraction, Implementor, ConcreteImplementor의 네 가지 요소로 구성됩니다.

1. Abstraction (추상화)

  • 클라이언트가 사용하게 되는 인터페이스로, 구현 객체를 참조하여 특정 작업을 수행합니다.

2. RefinedAbstraction (구체화된 추상화)

  • Abstraction을 상속받아 좀 더 구체적인 기능을 구현한 클래스입니다.

3. Implementor (구현자)

  • 실제 구현이 이루어지는 인터페이스로, ConcreteImplementor 클래스가 이 인터페이스를 구현합니다.

4. ConcreteImplementor (구체적 구현)

  • Implementor를 구현한 클래스들로, 구체적인 기능을 제공하는 클래스입니다.

3. Bridge 패턴의 구현 예시 (C#)

// Implementor: 구현 인터페이스
public interface IDrawingAPI
{
    void DrawCircle(double x, double y, double radius);
}

// ConcreteImplementor: 구체적인 구현
public class DrawingAPI1 : IDrawingAPI
{
    public void DrawCircle(double x, double y, double radius)
    {
        Console.WriteLine($"Drawing Circle in API1: ({x}, {y}) with radius {radius}");
    }
}

public class DrawingAPI2 : IDrawingAPI
{
    public void DrawCircle(double x, double y, double radius)
    {
        Console.WriteLine($"Drawing Circle in API2: ({x}, {y}) with radius {radius}");
    }
}

// Abstraction: 추상화
public abstract class Shape
{
    protected IDrawingAPI _drawingAPI;

    protected Shape(IDrawingAPI drawingAPI)
    {
        _drawingAPI = drawingAPI;
    }

    public abstract void Draw(); // 추상 메서드
}

// RefinedAbstraction: 구체화된 추상화
public class Circle : Shape
{
    private double _x, _y, _radius;

    public Circle(double x, double y, double radius, IDrawingAPI drawingAPI)
        : base(drawingAPI)
    {
        _x = x;
        _y = y;
        _radius = radius;
    }

    public override void Draw()
    {
        _drawingAPI.DrawCircle(_x, _y, _radius); // 구현부의 메서드를 호출
    }
}

위 코드에서 IDrawingAPI는 구현 인터페이스이며, DrawingAPI1과 DrawingAPI2는 실제 구현을 제공합니다.
Shape는 추상화된 클래스이고, Circle은 구체화된 추상화입니다.
Circle 클래스는 IDrawingAPI의 메서드를 사용하여 원을 그리는 작업을 수행합니다.

클라이언트 코드

public class Program
{
    public static void Main(string[] args)
    {
        Shape shape1 = new Circle(5, 10, 2, new DrawingAPI1());
        Shape shape2 = new Circle(7, 14, 3, new DrawingAPI2());

        shape1.Draw(); // Drawing Circle in API1: (5, 10) with radius 2
        shape2.Draw(); // Drawing Circle in API2: (7, 14) with radius 3
    }
}

클라이언트 코드에서는 Circle 객체를 생성할 때, 어떤 DrawingAPI를 사용할지 결정합니다.
이때 각기 다른 구현체를 사용하여 원을 그릴 수 있습니다.



4. Bridge 패턴의 장단점

장점:

  • 유연성: 추상화와 구현을 독립적으로 발전시킬 수 있어, 새로운 기능을 추가하기 용이합니다.
  • 코드 재사용: 다양한 구현을 동일한 추상화로 사용할 수 있어, 코드 중복을 줄이고 재사용성을 높입니다.
  • 구조 단순화: 클래스의 수를 줄일 수 있으며, 계층 구조를 단순화할 수 있습니다.

단점:

  • 복잡성 증가: 초기 설계가 복잡해질 수 있으며, 모든 경우에 필요한 것은 아닙니다.
  • 문서화 필요: 각 부분의 역할과 관계를 명확히 이해하고 문서화해야 합니다.


5. Bridge 패턴의 사용 사례

5.1. 그래픽 시스템

다양한 그래픽 API (OpenGL, DirectX 등)와 그 위에 존재하는 그래픽 객체(선, 원, 도형 등)를 분리하여, 새로운 그래픽 API를 쉽게 추가할 수 있도록 설계할 수 있습니다.

5.2. 데이터베이스와 ORM

데이터베이스의 여러 종류(MySQL, SQL Server, SQLite 등)와 ORM(Object-Relational Mapping) 구현을 분리하여, 새로운 데이터베이스를 추가할 때 기존 코드에 영향을 주지 않도록 할 수 있습니다.

5.3. UI 구성 요소

다양한 UI 프레임워크와 UI 컴포넌트를 분리하여, 새로운 UI 프레임워크를 사용하더라도 기존 컴포넌트를 그대로 활용할 수 있습니다.



Bridge 패턴은 추상화와 구현을 분리하여 둘의 독립적인 발전을 가능하게 하는 구조 패턴입니다.
이를 통해 코드의 유연성과 재사용성을 높일 수 있으며, 다양한 상황에서 활용될 수 있습니다.
Bridge 패턴을 이해하고 적용함으로써, 더 나은 소프트웨어 설계를 할 수 있습니다.

 

'Design Pattern' 카테고리의 다른 글

이터레이터(Iterator) 패턴  (1) 2024.10.17
커맨드(Command) 패턴  (0) 2024.10.17
프록시(Proxy) 패턴  (0) 2024.10.17
컴포지트(Composite) 패턴  (0) 2024.10.17
프로토타입(Prototype) 패턴  (0) 2024.10.14