관련 영상
브리지 패턴
위키피디아 - 브리지 패턴
설명 및 스도코드
- 브리지는 큰 클래스 또는 밀접하게 관련된 클래스들의 집합을 두 개의 개별 계층구조(추상화 및 구현)로 나눈 후 각각 독립적으로 개발할 수 있도록 하는 구조 디자인 패턴
브리지 패턴의 구조
- 추상화(Abstraction)
- 상위 수준의 제어 논리 제공
- 구현 객체에 의존해 실제 하위 수준 작업들을 수행
- 구현(Implementation Interface)
- 모든 구상 구현들에 공통적인 인터페이스를 선언하며, 추상화는 여기에 선언된 메서드들을 통해서만 구현 객체와 소통할 수 있다
- 추상화는 구현과 같은 메서드들을 나열할 수 있지만 보통은 구현이 선언한 다양한 원시 작업들에 의존하는 몇 가지 복잡한 행동들 선언
- 구상 구현(Concrete Implementation)
- 정제된 추상화(Refined Abstraction)
- 제어 논리의 변형들 제공, 부모처럼 일반 구현 인터페이스를 통해 다른 구현들과 작업
- 클라이언트(Client)
- 일반적으로 추상화와만 작업하나, 추상화 객체를 구현 객체들 중 하나와 연결하는 것도 클라이언트의 역할
브리지 패턴의 적용
- 어떠한 기능의 여러 변형을 가진 모놀리식 클래스를 나누고 정돈하려 할 때
- ex) 클래스가 다양한 데이터베이스 서버들과 작동할 수 있는 경우
- 여러 독립차원에서 클래스를 확장해야 할 때
- 각 차원에 대한 별도의 클래스 계층구조를 추출할 것을 제안
- 원래 클래스는 모든 작업을 자체적으로 수행하는 대신 추출된 계층구조들에 속한 객체들에 관련 작업들 위임
- 런타임에 구현을 전환할 수 있어야 할 때만
- 추상화 내부 구현 객체를 필드 값 변경으로 바꿀 수 있다.
- 브리지와 전략 패턴의 혼동을 가져온다
다른 패턴과의 관계
- 브리지는 일반적으로 사전에 설계되며, 앱의 다양한 부분을 독립적으로 개발할 수 있도록 한다. 반면에 어댑터는 일반적으로 기존 앱과 사용되어 원래 호환되지 않던 일부 클래스들이 서로 잘 작동하도록 한다.
- 브리지, 상태, 전략 패턴은 매우 유사한 구조로 되어 있으며, 어댑터 패턴도 이들과 어느 정도 유사한 구조로 되어 있다. 위 모든 패턴은 다른 객체에 작업을 위임하는 합성을 기반으로 한다. 하지만 이 패턴들은 모두 다른 문제들을 해결한다. 패턴은 특정 방식으로 코드의 구조를 짜는 레시피에 불과하지 않는다. 왜냐하면 패턴은 해결하는 문제를 다른 개발자들에게 전달할 수도 있기 때문이다.
- 추상 팩토리를 브리지와 함께 사용할 수 있다. 이 조합은 브리지에 의해 정의된 어떤 추상화들이 특정 구현들과만 작동할 수 있을 때 유용하다. 이런 경우에 추상 팩토리는 이러한 관계들을 캡슐화하고 클라이언트 코드에서부터 복잡성을 숨길 수 있다.
- 빌더를 브리지와 조합할 수 있다. 디렉터 클래스는 추상화의 역할을 하고 다양한 빌더들은 구현의 역할을 한다.
브리지 패턴을 이용해 구현한 Java 브러쉬 클래스
public interface Color {
String fill();
}
public class Red implements Color {
public String fill() {
return "발간색";
}
}
public class Blue implements Color {
@Override
public String fill() {
return "파란색";
}
}
public abstract class Brush {
protected Color color;
protected Brush(Color color) {
this.color = color;
}
public abstract String draw();
}
public class HBPencil extends Brush {
public static final String type = "[HB 연필]";
public HBPencil(Color color) {
super(color);
}
@Override
public String draw() {
return type + " " + color.fill();
}
}
public class MonoLine extends Brush {
public static final String type = "[모노라인]";
public MonoLine(Color color) {
super(color);
}
@Override
public String draw() {
return type + " " + color.fill();
}
}
class BrushTest {
@Test
@DisplayName("브리지 패턴 테스트")
void brushColorTest() {
Brush redBrush = new HBPencil(new Red());
Assertions.assertThat("[HB 연필] 빨간색".equals(redBrush.draw()));
Brush blueBrush = new MonoLine(new Blue());
Assertions.assertThat("[모노라인] 파란색".equals(blueBrush.draw()));
}
}