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

어댑터 패턴(Adapter Pattern)

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

인터페이스가 용도에 맞지 않을 때 용도에 맞도록 중간에서 변환한다.

6.2 어댑터

일반적인 어댑터의 예입니다. Line을 Point들로 변환하는 어댑터를 설명합니다.

 

Point들을 그리는 기능만 있는데 Line을 그리려면 어떻게 해야 하나?

void DrawPoints(CPaintDC& dc, std::vector<Point>::iterator start, std::vector<Point>::iterator end)


다음과 같이 라인을 점들로 변환하는 어댑터를 구현합니다.

이 구현은 수직, 수평인 라인들만을 다루고 나머지는 무시합니다.

struct LineToPointAdapter
{
 typedef vector<Point> Points;
 
 LineToPointAdapter(Line& line)
 {
  int left = min(line.start.x, line.end.x);
  int right = max(line.start.x, line.end.x);
  int top = min(line.start.y, line.end.y);
  int bottom = max(line.start.y, line.end.y);
  int dx = right - left;
  int dy = line.end.y - line.start.y;
 
  if (dx == 0)
  {
   // 수직
   for (int y = top; y <= bottom; ++y)
   {
    points.emplace_back(Point{ left,y });
   }
  }
  else if (dy == 0)
  {
   // 수평
   for (int x = left; x <= right; ++x)
   {
    points.emplace_back(Point{ x, top });
   }
  }
 }
 
 virtual Points::iterator begin() { return points.begin(); }
 virtual Points::iterator end() { return points.end(); }
private:
 Points points;
};

 

이 LineToPointAdapter를 사용하는 코드는 다음과 같습니다.

LineToPointAdapter lpo {line};
DrawPoints(dc, lpo.begin(), lpo.end());


캐싱 어댑터

LineToPointAdapter는 매번 Points로 변환 하기 때문에 이 단점을 개선한 이 변환 결과를 캐시하는 캐싱 어댑터 구현을 설명합니다.

 

화면이 업데이트 될때마다 DrawPoints()가 불리면 반복적으로 점으로 변환한다. 이를 피하기 위해 캐싱을 구현한다.

캐싱을 하여 매번 Points로 변환하지 않도록 하였다.

 

라인이 바뀔 경우에는 어떻게 할 것인가? 반복적인 변환을 피하기위해 각각의 선분을 유일하게 식별해보자.

Hash Function을 이용하여 식별을 구현하였으며 이 것이 바로 LineToPointCachingAdapter이다.

struct LineToPointCachingAdapter
{
 typedef vector<Point> Points;
 
 LineToPointCachingAdapter(Line& line)
 {
  boost::hash<Line> hash;
  line_hash = hash(line);
  if (cache.find(line_hash) != cache.end())
   return; // 이미 캐싱하고 있는 라인.
 
  Points points;
 
  int left = min(line.start.x, line.end.x);
  int right = max(line.start.x, line.end.x);
  int top = min(line.start.y, line.end.y);
  int bottom = max(line.start.y, line.end.y);
  int dx = right - left;
  int dy = line.end.y - line.start.y;
 
  if (dx == 0)
  {
   for (int y = top; y <= bottom; ++y)
   {
    points.emplace_back(Point{ left,y });
   }
  }
  else if (dy == 0)
  {
   for (int x = left; x <= right; ++x)
   {
    points.emplace_back(Point{ x, top });
   }
  }
 
  cache[line_hash] = points; // 새로운 라인 캐싱한다.
 }
 
 virtual Points::iterator begin() { return cache[line_hash].begin(); }
 virtual Points::iterator end() { return cache[line_hash].end(); }
private:
 size_t line_hash;
 static map<size_t, Points> cache;
};

 

[독서 리뷰] - 모던 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