브리지 패턴

이정석·2023년 5월 30일
0

디자인패턴

목록 보기
6/23
post-thumbnail

브리지 패턴이란?

추상을 구현으로부터 분리하여 독립적으로 변하게 하는 패턴이다. 추상과 구현이 헷갈릴수도 있지만 추상은 로직을 정의하는 부분, 구현부는 추상부에서 정의한 연산을 실제로 구현하는 부분이다.


문제상황

Shape객체의 모양은 CircleSquare가 있고 색깔에는 RedBlue가 있다.
1. 여러 모양(Circle, Square)과 색깔을 포함하는 Shape객체가 있다고 하자.

abstract class Shape {
    abstract void draw();
}

2. 사각형에는 빨간색(Red)과 파란색(Blue)이 있다.

class RedSquare extends Shape {
    void draw() {
        System.out.println("Drawing a red square");
    }
}

class BlueSquare extends Shape {
    void draw() {
        System.out.println("Drawing a blue square");
    }
}

3. 원에도 빨간색(Red)과 파란색(Blue)이 있다.

class RedCircle extends Shape {
    void draw() {
        System.out.println("Drawing a red circle");
    }
}

class BlueCircle extends Shape {
    void draw() {
        System.out.println("Drawing a blue circle");
    }
}

4. 새로운 색깔인 노란색(Yellow)이 추가됐다고 하면 노란색 사각형과 노란색 원이 추가되어야 한다.

class YellowSquare extends Shape {
    void draw() {
        System.out.println("Drawing a yellow square");
    }
}

class YellowCircle extends Shape {
    void draw() {
        System.out.println("Drawing a yellow circle");
    }
}

5. 새로운 모양인 삼각형(Triangle)이 추가됐다고 하면 빨간색, 파란색, 노란색 삼각형을 추가해야 한다.

class RedTriangle extends Shape {
    void draw() {
        System.out.println("Drawing a red triangle");
    }
}

class BlueTriangle extends Shape {
    void draw() {
        System.out.println("Drawing a blue triangle");
    }
}

class YellowTriangle extends Shape {
    void draw() {
        System.out.println("Drawing a yellow triangle");
    }
}

위 문제상황은 다음과 같다.

  • 새로운 모양이 추가되면 모든 색깔에 대한 코드를 작성해야 한다.
  • 새로운 색깔이 추가되면 모든 모양에 대한 코드를 작성해야 한다.
    이 구조는 모양과 색깔이 많아지면 많아질수록, 추가해야 하는 코드는 기하급수적으로 늘어난다. 이런 상황은 색깔-모양을 한번에 정의하려고 하기 때문에 발생한다. 즉, 모양(Shape)과 색깔(Color)와의 강한 결합에 의해 발생한다.

    빨간색 원을 그리려 하지 말고, 빨간색으로 그리도록 하자!
    모양색깔을 분리하자!


구조

  1. Abstraction: 클라이언트가 사용할 인터페이스를 정의한 클래스로 기본적인 연산을 선언하고 Implementation에 대한 레퍼런스를 가지고 있다. 보통 인터페이스가 아닌 추상 클래스로 정의한다.
  2. Implementation: Abstaction에서 선언한 연산을 실제로 구현하는 인터페이스를 정의한 클래스이다.
  3. RefinedAbstraction: 재정의한 추상부를 나타내는 클래스로 Abstaction를 확장하여 더 복잡한 기능을 제공하는 클래스를 만들 수 있다.
  4. ConcreteImplementation: 구현부 인터페이스를 구현하고, Abstaction에서 선언한 메서드들을 실제로 구현하는 클래스이다.

코드(JAVA)

위 문제상황에 브릿지 패턴을 적용한 코드는 다음과 같다.
1. Color

interface Color {
    void applyColor();
}

class Red implements Color {
    public void applyColor() {
        System.out.println("red");
    }
}

class Blue implements Color {
    public void applyColor() {
        System.out.println("blue");
    }
}

구현부인 Color인터페이스와 실제 구현하는 Red, Blue클래스
2. Shape

abstract class Shape {
    protected Color color;
    public Shape(Color color) {
        this.color = color;
    }
    abstract void draw();
}

class Square extends Shape {
    public Square(Color color) { bsuper(color); }
    public void draw() {
        System.out.print("Drawing square in ");
        color.applyColor();
    }
}

class Circle extends Shape {
    public Circle(Color color) { super(color); }
    public void draw() {
        System.out.print("Drawing circle in ");
        color.applyColor();
    }
}

추상부인 Shape클래스와 이를 재정의한 Square, Circle클래스이다. Shape클래스는 추상클래스인 것을 확인하자.


상속관계 vs 집합관계

브릿지 패턴은 Aggregation으로 Color에 대한 레퍼런스를 Shape가 가지고 있다. 이것을 상속관계로 표현할 수 있는데 상속을 이용한것과 집합을 이용한 것은 어떤 차이가 있을까?

상속집합
실행 시 구현객체 하나만 존재한다.실행 시 추상객체와 구현객체가 존재한다.
컴파일 시 고정된다.추상객체와 구현객체의 연결이 런타임에 바뀔 수 있다.

상속을 이용하면 하나의 객체를 유지할 수 있다는 장점이 있지만 추상부와 구현부를 교체할 수 없다는 단점이 있다.

런타임에 추상부와 구현부가 바뀌지 않는다는 상황이 보장된다면? 상속이 더 효율적인가?

참고자료

  1. Refactoring Guru: 디자인 패턴 - 브리지 패턴
profile
게임 개발자가 되고 싶은 한 소?년

0개의 댓글