🎈 브릿지 패턴 (Bridge Pattern)
• 새로운 인터페이스를 정의하여
기존 프로그램 변경없이 기능 확장할 수 있다.
• 기능을 독립적으로 확장할 수 있다면
상세한 기능을 외부로부터 숨길 수 있는 은닉 효과도 얻을 수 있다.
• 디자인 패턴 중에서 구조 패턴에 해당한다.
[예제 코드]
#include <iostream>
// 추상 구현 클래스
class Implementor {
public:
virtual void operationImpl() = 0;
};
class ConcreteImplementor : public Implementor {
public:
void operationImpl() override {
std::cout << "구현 클래스" << std::endl;
}
};
// 추상화 클래스
class Abstraction {
public:
Abstraction(Implementor* impl) : implementor(impl) {}
virtual void operation() {
implementor->operationImpl();
}
protected:
Implementor* implementor;
};
class RefinedAbstraction : public Abstraction {
public:
RefinedAbstraction(Implementor* impl) : Abstraction(impl) {}
void additionalOperation() {
std::cout << "확장 추상화 클래스" << std::endl;
}
};
void main() {
Implementor* impl = new ConcreteImplementor();
RefinedAbstraction* abstraction = new RefinedAbstraction(impl);
abstraction->operation();
abstraction->additionalOperation();
}
Abstraction과 Implementor 사이의 브릿지를 통해
서로 독립적으로 확장할 수 있게 하였다.
🎈 브릿지 패턴 장단점
+ 구현과 추상화 분리: 독립적으로 확장하거나 수정 가능
+ 다중 플랫폼 지원하는 코드 개발시 유용하다.
- 복잡성 증가: 하나의 클래스를 (추상 + 구현) 계층으로 분리하기에
규모가 작은 프로젝트에서는 복잡해지는 편이다.
[예제 코드] - 브릿지 패턴 적용 X
#include <iostream>
// 모양을 나타내는 클래스
class Shape {
public:
virtual void draw() = 0;
};
// 구체적인 모양 클래스 - 원
class Circle : public Shape {
public:
void draw() override {
std::cout << "원을 그립니다." << std::endl;
}
};
// 구체적인 모양 클래스 - 사각형
class Rectangle : public Shape {
public:
void draw() override {
std::cout << "사각형을 그립니다." << std::endl;
}
};
void main() {
Shape* circle = new Circle();
Shape* rectangle = new Rectangle();
circle->draw();
rectangle->draw();
}
클래스를 상속하면 구현과 추상 개념이 결합이 강하다.
이 경우 상속 클래스를 수정하거나 확장하기 어려워진다.
override 하여 재정의하여도 부모 클래스의 메서드를 모두 포함해야 한다.
상속으로 계속 기능을 확장하며 최종 클래스는 무거워진다.
[예제 코드] - 브릿지 패턴 적용
모양(Shape)과 그림 그리기 방식(DrawingAPI)을 분리
느슨한 결합으로 다양한 모양과 구현 방식을 조합할 수 있다.
#include <iostream>
// 구현 방식을 나타내는 인터페이스
class DrawingAPI {
public:
virtual void drawShape() = 0;
};
// 구체적인 구현 방식 - 원
class CircleDrawingAPI : public DrawingAPI {
public:
void drawShape() override {
std::cout << "원을 그립니다." << std::endl;
}
};
// 구체적인 구현 방식 - 사각형
class RectangleDrawingAPI : public DrawingAPI {
public:
void drawShape() override {
std::cout << "사각형을 그립니다." << std::endl;
}
};
// ------------------------------------------
class Shape {
public:
virtual void draw() = 0;
};
// 모양 클래스와 구현 방식을 연결
class Circle : public Shape {
public:
Circle(DrawingAPI* drawingAPI) : drawingAPI(drawingAPI) {}
void draw() override {
drawingAPI->drawShape();
}
private:
DrawingAPI* drawingAPI;
};
class Rectangle : public Shape {
public:
Rectangle(DrawingAPI* drawingAPI) : drawingAPI(drawingAPI) {}
void draw() override {
drawingAPI->drawShape();
}
private:
DrawingAPI* drawingAPI;
};
// ------------------------------------------
void main() {
CircleDrawingAPI circleAPI;
RectangleDrawingAPI rectangleAPI;
Circle circle(&circleAPI);
Rectangle rectangle(&rectangleAPI);
circle.draw();
rectangle.draw();
}
🎈 브릿지 패턴 활용
• 그래픽 라이브러리: 그래픽 요소와 출력 장치 연결
• 데이터베이스 연결: 다른 DBMS 연결 지원
• 리모컨 및 기기 컨트롤: 다양한 기기간 연결 관리
[예제 코드] - 브릿지 패턴 적용 전
#include <iostream>
#include <string>
// Book 클래스
class Book {
public:
Book(const std::string& title, const std::string& author)
: title(title), author(author) {}
void print() {
std::cout << "Title: " << title << std::endl;
std::cout << "Author: " << author << std::endl;
}
private:
std::string title;
std::string author;
};
void main() {
Book book("디자인 패턴", "까망 하르망");
book.print();
}
도서 관리시스템으로 간단하게 책(Book)과 출력(Printer) 기능이 있다.
예제 코드] - 브릿지 패턴 적용 후
#include <iostream>
#include <string>
// 출력 인터페이스
class Printer {
public:
virtual void print(const std::string& content) = 0;
};
// 구체적인 출력 클래스 - 화면에 출력
class ScreenPrinter : public Printer {
public:
void print(const std::string& content) override {
std::cout << "Screen Output: " << content << std::endl;
}
};
// 구체적인 출력 클래스 - 프린터로 출력
class PrinterPrinter : public Printer {
public:
void print(const std::string& content) override {
std::cout << "Printer Output: " << content << std::endl;
}
};
// Book 클래스
class Book {
public:
Book(const std::string& title, const std::string& author, Printer* printer)
: title(title), author(author), printer(printer) {}
void print() {
printer->print("Title: " + title);
printer->print("Author: " + author);
}
private:
std::string title;
std::string author;
Printer* printer;
};
void main() {
ScreenPrinter screenPrinter;
PrinterPrinter printerPrinter;
Book book1("디자인 패턴", "까망 하르망", &screenPrinter);
Book book2("디자인 패턴", "까망 하르망", &printerPrinter);
book1.print();
book2.print();
}
Printer 인터페이스로 출력 방식을 경정할 수 있다.
이로인해 Book 클래스는 수정하지 않아도
다양한 출력 방식을 지원할 수 있다.
🎈 다른 디자인 패턴과 비교
Bridge 패턴과 마찬가지로 인터페이스를 조정한다.
하지만 어댑터 패턴은 호환되지 않는 인터페이스를
가능하도록 인터페이스로 변환하는 것에 차이가 있다.
또한, 어댑터 패턴이 완성된 코드를 결합하는 것이라면
브릿지 패턴은 설계 단계에서 확장을 고려해서 추상화 하는 것이다.
• 전략 (Strategy)
객체 간의 관계를 느슨하게 만들지만 목적과 사용 시점이 다르다.
브릿지 패턴은 주로 추상화와 구현을 분리하여
복잡한 클래스 계층 구조를 간소화하여 새로운 기능을 쉽게 추가/변경 한다.
반면에 전략 패턴은 알고리즘을 분리하여 Rumtime에 선택할 수 있게 한다.
데코레이터 패턴과는 구조적인 측면에서 다르다.
데코레이터 패턴이 Runtime에 객체 동작을 변경/확장할 수 있고
브릿지 패턴은 추상화와 구현을 분리해서 계층 구조를 관리하는데 중점을 둔다.
'까망 동네 > 디자인 패턴' 카테고리의 다른 글
[디자인패턴] 장식자 패턴 (Decorator) (2) | 2023.11.01 |
---|---|
[디자인패턴] 프로토타입 (Prototype Pattern) (1) | 2023.10.31 |
[디자인 패턴] 중재자 패턴 (Mediator Pattern) (0) | 2023.10.22 |
[디자인 패턴] 빌더 패턴 (Builder Pattern) (2) | 2023.10.21 |
💻 [디자인패턴] 전략 패턴 (Strategy Pattern) (1) | 2023.10.19 |
댓글