프로그래밍 일반/디자인 패턴

브릿지 패턴(Bridge Pattern)

지노윈 2019. 12. 8. 16:42
반응형

기능 클래스(껍데기)와 구현 클래스(실제 구현)를 서로 연결하는 패턴입니다.

Bridge하면 무엇이 떠오르나요?

브릿지가 서로 떨어진 두 곳을 연결 하듯이 브릿지 패턴 또한 서로 떨어진 두 기능을 연결합니다. 이것이 핵심입니다.

즉, 기능과 구현을 서로 연결하는 것입니다.

Pimpl(Pointer to Implementation) 관례

구현부를 포인터로 참조하는 관례를 뜻한다.

클래스의 구현부를 다른 클래스(PersonImpl)에 숨깁니다. PersonImpl 구현이 모두 .cpp 파일에 정의하는 것이 핵심입니다.

Person.h

struct Person

{

  std::string name;



  class PersonImpl; // 전방 선언

  PersonImpl *impl; // 구현은 모두 cpp 파일에서 함



  Person();

  ~Person();



  void greet();

};

Person.cpp

#include "Person.h"
 
struct Person::PersonImpl
{
  void greet(Person* p);
};
 
void Person::PersonImpl::greet(Person* p)
{
  printf("hello %s", p->name.c_str());
}
 
Person::Person() : impl(new PersonImpl){}
 
Person::~Person()
{
  delete impl;
}

Pimpl의 3가지 장점Person.cpp

  • 클래스 구현부의 상당 부분을 감출 수 있습니다.
    public만 노출 시키고 protected, private은 모두 Pimpl로 구현하여 감출 수 있습니다.
  • 바이너리 호환성을 보증하기 쉬워집니다.
    숨겨진 구현 클래스에 대한 수정은 바이너리 호환성에 영향을 미치지 않습니다.
  • 불필요한 헤더까지 인클루드 하지 않아도 됩니다.
    즉, Person 클래스의 public 선언에 필요한 해더들만 인클루드합니다.

이러한 장점들은 깨끗하고 안정적인 헤더를 유지할 수 있게 해줍니다.

덤으로 컴파일 소요 시간도 줄여줍니다.

Pimpl은 브릿지 패턴의 좋은 예입니다.

브릿지

서로 다른 구현을 연결하며 실제 구현을 다른 클래스에 위임합니다.

여기서는 기하 도형 클래스와 렌더링 클래스를 연결하며 렌더링 구현을 다른 클래스에 위임하였습니다.

 

기하 도형 클래스, 기하 도형을 구현하였으며 렌더링 구현을 다른 클래스에 위임합니다.

기하 도형 클래스

struct Shape
{
protected:
  Renderer& renderer;   // 브릿지, 렌더링 실제 구현을 위임합니다.
  Shape(Renderer& renderer) : renderer{ renderer } {}
public:
  virtual void draw() = 0;
  virtual void resize(float factor) = 0;
};
 
struct Circle : Shape
{
  float x, y, radius;
 
  void draw() override
  {
    renderer.render_circle(x, y, radius);
  }
 
  void resize(float factor) override
  {
    radius *= factor;
  }
 
  Circle(Renderer& renderer, float x, float y, float radius)
    : Shape{renderer},{x}, y{y}, radius{radius}
  {
  }
};

브릿지, 렌더 클래스 구현브릿지 클래스, 벡터 렌더러와 래스터 렌더러를 구현합니다.

struct Renderer
{
  virtual void render_circle(float x, float y, float radius) = 0;
};
 
struct VectorRenderer : Renderer
{
  void render_circle(float x, float y, float radius) override
  {
    cout << "Drawing a vector circle of radius " << radius << endl;   
  }
};
 
struct RasterRenderer : Renderer
{
  void render_circle(float x, float y, float radius) override
  {
    cout << "Rasterizing circle of radius " << radius << endl;
  }
};


브릿지 RasterRenderer를 이용해 원을 그립니다.

RasterRenderer rr;
Circle raster_circle{ rr, 5,5,5 };
raster_circle.draw();
raster_circle.resize(2);
raster_circle.draw();

 

[독서 리뷰] - 모던 C++ 디자인 패턴

 

모던 C++ 디자인 패턴

[객체 지향 프로그래밍/디자인 패턴] - 빌더 패턴(Builder Pattern) [분류 전체보기] - 디자인 패턴 [객체 지향 프로그래밍/디자인 패턴] - 팩토리 패턴(Factory pattern) [객체 지향 프로그래밍/디자인 패턴] -..

devjino.tistory.com

코드 참고 : https://cpp-design-patterns.readthedocs.io/en/latest/
 

Welcome to C++ Design Patterns’s documentation! — C++ Design Patterns 0.0.1 documentation

© Copyright 2018, Hans-J. Schmid Revision 786c83f8.

cpp-design-patterns.readthedocs.io