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

French Marigold·2024년 3월 20일
2

디자인패턴

목록 보기
2/10
post-thumbnail

정의

  • 브릿지 패턴(Bridge Pattern)이란 추상화 계층과 구현 계층을 분리하여 시스템의 확장성과 유지보수성을 높이는 패턴이다.
  • 다양한 모양의 그림을 그릴 수 있는 어플리케이션을 개발하고 있다고 가정해보자. 이 어플리케이션은 원, 사각형, 삼각형 등 다양한 모양의 도형을 그릴 수 있고 빨강, 파랑, 초록 등의 색깔을 사용하여 도형의 색깔을 칠할 수 있다. 만약에 빨간색 원을 만든다고 가정한다면 다음과 같은 코드를 사용할 수 있을 것이다.
class RedCircle {
    func rotate() {
        print("Rotate RedCircle")
    }
    
    func move() {
        print("Move RedCircle")
    }
    
    func upScale() {
        print("Upscale RedCircle")
    }
    
    func downScale() {
        print("Downscale RedCircle")
    }
}

let redCircle = RedCircle()
redCircle.rotate()
  • 하지만 해당 코드는 빨간 원이라는 도형 밖에 생성하지 못하는 확장성이 낮은 코드이다. 예를 들어, 파란색 사각형이 필요하다면? 녹색 삼각형이 필요하다면? 새로운 색깔이나 도형이 필요할 때마다 일일이 클래스를 생성하면 너무 많은 클래스들이 생겨나게 된다.
  • 이 문제는 한 클래스가 ‘도형’ 과 ‘색깔’을 변경하는 책임을 모두 맡으려고 하기에 발생하는 문제이다. 브릿지 패턴(Bridge Pattern)은 해당 문제를 계층을 분리하는 방식으로 전환하여 해결한다. 즉, ‘도형’ 계층과 ‘색깔’ 계층을 분리하여 생각한다는 것이다. ‘도형’ 계층이 삼각형, 사각형, 원 등을 생성해내고 ‘색깔’ 계층이 빨강, 초록, 파랑 등의 색깔을 생성해낸 후, ‘도형’ 계층이 ‘색깔’ 계층을 참조하여 사용할 수 있는 방식이다. 서로 다른 계층을 연결(참조)해주는 역할을 바로 Bridge 라고 한다.

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

  • Abstraction
    • 추상 계층의 프로토콜 및 클래스를 정의한다.
    • 구현 계층의 클래스 인스턴스를 참조하는 Bridge 영역을 생성한다.
  • RefinedAbstraction
    • Abstraction 내부의 기능을 추가하거나 확장한다.
  • Implementor
    • 구현 계층의 프로토콜을 정의한다.
  • ConcreteImplementor
    • Implementor 프로토콜을 구체적으로 구현한다.

브릿지 패턴 적용 과정 예시

  1. 구현 계층의 프로토콜 (Implementor)을 정의한다.
// Implementor
protocol Coloring {
    var colorName: String { get set }
    func createColor()
}
  1. Implementor 프로토콜을 구체적으로 구현 (ConcreteImplementor)한다. Implementor를 구체적으로 구현함으로써 해당 프로토콜로부터 파생되는 다양한 색깔 객체를 만들어낼 것이다.
// ConcreteImplementor
class Green: Coloring {
    var colorName: String
    
    init(colorName: String) {
        self.colorName = colorName
    }
    
    func createColor() {
        print(colorName)
    }
}

// ConcreteImplementor
class Red: Coloring {
    var colorName: String
    
    init(colorName: String) {
        self.colorName = colorName
    }
    
    func createColor() {
        print(colorName)
    }
}
  1. 그 후, 추상 계층의 프로토콜 및 클래스(Abstraction)를 정의한다. Abstraction 부분은 추상 계층과 구현 계층을 연결하는 Bridge가 존재해야 함을 기억해야 한다.
// Abstraction
class Shape {
    // Bridge : 서로 다른 계층의 객체들과 연결하는 다리 역할
    var coloring: Coloring
    
    // 도형의 모양 생성
    var shape: String
    
    init(coloring: Coloring, shape: String) {
        self.coloring = coloring
        self.shape = shape
    }
    
    func create() {
        print("\(coloring.colorName) \(shape) 생성")
    }
}

let greenSquare = Shape(coloring: Red(colorName: "녹색"), shape: "사각형")
greenSquare.create() // 녹색 사각형 생성
  1. Abstraction 내부의 기능을 추가하거나 확장 (RefinedAbstraction)할 수 있다. 이 때 확장할 수 있는 경우는 두 가지인데,
    • Abstraction을 상속받아서 메소드를 추가한다.
    • extension을 이용해서 메소드를 추가한다. (Swift에서는 이 방법이 더 편한 것 같다.)
// Abstraction을 상속받아서 메소드를 추가
class RotateShape: Shape {
    // Abstraction 내부의 기능을 더 추가 및 확장할 수 있다.
    func rotate() {
        print("\(coloring.colorName) \(shape) 돌아라")
    }
}

// extension을 이용해서 메소드를 추가
extension Shape {
    // Abstraction 내부의 기능을 더 추가 및 확장할 수 있다.
    func rotate() {
        print("\(coloring.colorName) \(shape) 돌아라")
    }
}

패턴 사용 시기

  • 하나의 클래스가 너무 많은 책임을 떠안고 있을 경우, 수행 역할을 알맞게 나눠야 할 때

패턴의 장점

  • OCP를 만족한다 ⇒ 직접 메소드 안에서 코드를 수정하는 것이 아닌 추상화 계층 내에서 기능을 확장시켜나가는 방식을 취함.
  • SRP를 만족한다 ⇒ 추상화 계층은 사용하는 쪽의 입장에만 관심이 있고, 구현 계층은 오직 구현에만 관심이 있다. 즉, 책임이 단일하다.
  • 추상화 계층과 구현 계층의 관심사를 분리하여 하나를 변경해도 다른 하나에 영향을 주지 않게 하여 변경하기 쉽게 만든다.

패턴의 단점

  • 계층 구조가 늘어나 코드가 복잡해진다.
  • 코드를 이해하기 쉽게끔 세심하게 설계해야 함. 즉, 개발 시간이 증가한다.

참고 문헌

profile
꽃말 == 반드시 오고야 말 행복

4개의 댓글

comment-user-thumbnail
2024년 3월 20일

브릿지패턴은 개념은 알고있지만 적용해본적은 없는 디자인패턴인거같아요 ㅎㅎ...
역시 실제로 적용하는건 언제나 어려운일인것같네요
객체지향원칙을 준수할수있다는 장점이있지만 역시나 계층구조가 늘어나고 코드점핑이늘어나는부분이 도입을 망설이게되는 이유가될수도있겠다는생각이드네요

원칙을 지키기 위한 디자인패턴을 도입했을때 발생하는 추상화나 계층추가문제로인해 직관성이 떨어지고 시간이좀더 걸리는부분을 조율을 잘해야겠다는 생각이드네요 ㅎㅎ

1개의 답글
comment-user-thumbnail
2024년 3월 21일

브릿지 패턴이 흔히 Dependency Injection가 가능하도록 클래스를 구성할 때 사용하는 방법인거죠?
클래스에서 내부 프로퍼티로 다른 인스턴스 들고 있어야 할 때 타입을 protocol로 선언하는 거죠

내가 어떤 패턴을 쓰고 있는지 명확하게 모르는 게 웃기기도 하면서 갈 길이 멀다는 생각이 드네요 ㅋㅋ

1개의 답글