브릿지 패턴이란? |
기능클래스계통과 구현클래스 계통으로 분리하여 각자 독립적으로 변형과 확장이 가능하도록 하는 패턴
기능클래스계통이란 새로운 기능을 추가로 구현하고 싶은 경우 사용하는 클래스계통이며
A클래스가 있을때 A클래스에 새로운 기능을 추가하고 싶다면 Child_A클래스를 만들어 A클래스를 상속받고
Child_A클래스에 새로운 기능을 추가한 후 Child_A객체를 사용하면 된다.
이런식으로 새로운 기능을 추가하고 싶은 경우 사용하는것이 기능클래스계통이다.
구현클래스계통이란 추상클래스에 인터페이스를 작성하고 하위클래스에서 해당 인터페이스들을 실제로 구현하는 방식을 말한다.
클래스계층이 하나만 있다면
위 사진처럼 기능클래스 계층과 구현클래스 계층이 뒤죽박죽 되므로 두 계층으로 나눈 후 Bridge(다리)를 놓는 패턴
언제 사용하는가
- 설계단계부터 확장성을 고려해서 적용하는 패턴이며 컴포넌트간 다양한 조합이 가능할때 효과적이다.
- 기존시스템에 부수적인 새로운 기능들을 지속적으로 추가할때 기능쪽 클래스 계층에 클래스를 추가하면 되므로 추상쪽은 건들 필요가 없음
- 새로운 인터페이스 정의로 기존 프로그램 변경 없이 기능확장 가능
- 구현 세부사항을 숨기기 위해 사용할수도 있다.
브릿지 패턴의 구조 |
- Abstraction : 기능 계층의 최상위클래스이며
구현부(추상클래스)의 객체를 멤버로 갖고 이를 이용해서 구현부 메서드를 호출함
- RefinedAbstracton : 기능 계층에서 새로운 부분을 확장한 클래스
- Implementor : 추상클래스로써 인터페이스 정의
- ConcreteImplementor : 추상클래스의 하위클래스로 실제 기능을 구현한 클래스
구현 코드 예시 |
1) 구현 코드
#include <iostream>
using namespace std;
/**************** 구현클래스 계통 ****************/
class Color
{
public:
virtual void fill() = 0;
};
class Red : public Color
{
public:
void fill() override { cout << "Red\n"; }
};
class Green : public Color
{
public:
void fill() override { cout << "Green\n"; }
};
/**************** 기능클래스 계통 ****************/
class Shape
{
protected:
Color* color; // Bridge
public:
Shape(Color* c) : color(c){}
void Draw() { cout << "Draw\n"; }
virtual void applyColor() {};
};
class Triangle : public Shape
{
public:
Triangle(Color* c) : Shape(c) {}
void applyColor() override {
cout << "Triangle filled with color ";
color->fill();
}
};
class Pentagon : public Shape
{
public:
Pentagon(Color* c) : Shape(c) {}
void applyColor() override {
cout << "Pentagon filled with color ";
color->fill();
}
};
/******************* main함수 *******************/
int main()
{
Color* red = new Red();
Shape* tri = new Triangle(red);
tri->applyColor();
Color* green = new Green();
Shape* pen = new Pentagon(green);
pen->applyColor();
return 0;
}
2) 실행결과
Pimpl |
Pointer to Implementation의 약자
C++에서 구현 세부사항을 캡슐화하고 추상 인터페이스만 노출시키는 디자인 패턴으로 브릿지 패턴의 좋은 예시
구현이 변경되더라도 내부 구현은 캡슐화되어있고 외부 인터페이스는 유지되므로 외부코드는 수정하지 않아도 이전 버전과 호환된다.
※ 참고 문헌
https://m.blog.naver.com/tradlinx0522/220928963011