반응형
인터페이스가 용도에 맞지 않을 때 용도에 맞도록 중간에서 변환한다.
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;
};
코드 참고 : https://cpp-design-patterns.readthedocs.io/en/latest/
'프로그래밍 일반 > 디자인 패턴' 카테고리의 다른 글
컴포지트 패턴(Composite Pattern) (0) | 2019.12.08 |
---|---|
브릿지 패턴(Bridge Pattern) (0) | 2019.12.08 |
싱글턴 패턴(Singleton Pattern) (0) | 2019.12.08 |
프로토타입 패턴(Prototype Pattern) (0) | 2019.12.08 |
팩토리 패턴(Factory pattern) (2) | 2019.11.17 |