추상을 구현으로부터 분리하여 독립적으로 변하게 하는 패턴이다. 추상과 구현이 헷갈릴수도 있지만 추상은 로직을 정의하는 부분, 구현부는 추상부에서 정의한 연산을 실제로 구현하는 부분이다.
Shape객체의 모양은 Circle과 Square가 있고 색깔에는 Red와 Blue가 있다.
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");
}
}
위 문제상황은 다음과 같다.
빨간색 원을 그리려 하지 말고,원을빨간색으로 그리도록 하자!
모양과색깔을 분리하자!
위 문제상황에 브릿지 패턴을 적용한 코드는 다음과 같다.
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클래스는 추상클래스인 것을 확인하자.
브릿지 패턴은 Aggregation으로 Color에 대한 레퍼런스를 Shape가 가지고 있다. 이것을 상속관계로 표현할 수 있는데 상속을 이용한것과 집합을 이용한 것은 어떤 차이가 있을까?
| 상속 | 집합 |
|---|---|
| 실행 시 구현객체 하나만 존재한다. | 실행 시 추상객체와 구현객체가 존재한다. |
| 컴파일 시 고정된다. | 추상객체와 구현객체의 연결이 런타임에 바뀔 수 있다. |
상속을 이용하면 하나의 객체를 유지할 수 있다는 장점이 있지만 추상부와 구현부를 교체할 수 없다는 단점이 있다.
런타임에 추상부와 구현부가 바뀌지 않는다는 상황이 보장된다면? 상속이 더 효율적인가?