Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- 모던C++디자인패턴
- 팩터리 메서드
- 디자인패턴
- 프로토타입 패턴
- 동적 데코레이터
- 팩터리
- 컴포지트 패턴
- 빌더
- 단순한 빌더
- 데커레이터
- 프로토타입 중복처리
- 흐름식 빌더
- 추상 팩터리
- 싱글턴
- 함수형 팩터리
- 데커레이터 패턴
- 그루비 스타일 빌더
- 싱글톤 패턴
- 싱글턴 패턴
- 디자인 패턴
- 브릿지 패턴
- 컴포지트
- 빌더 패턴
- 프로토타입
- 내부 팩터리
- 팩터리 패턴
- 동적 데커레이터
- 브릿지
- 컴포지트 빌더
- 싱글톤
Archives
- Today
- Total
GGym's Practice Notes
9-2. 데커레이터_정적 데커레이터 본문
resize() 멤버 함수는 Shape 인터페이스와 관계가 없기 때문에 데커레이터에서 호출할 수 없다.
보통의 상속 대신 MixIn 상속이라 불리는 방식을 이용한다.
static_assert를 이용해 Shape이외의 타입이 지정되는 것을 막는다.
template <typename T> struct ColoredShape : T{
static_assert(is_base_of<Shape, T>::value,
"template argument must be a Shape");
string color;
string str() const override{
ostringstream oss;
oss << T::str() << " has the color " << color;
return oss.str();
}
}; // TransparentShape<T>의 구현은 생략...
ColoredShape<T>와 TransparentShape<T>의 구현을 기반으로 하여 색상이 있는 투명한 도형을 합성할 수 있다.
ColoredShape<TransparentShape<Square>> square{"blue"};
square.size = 2;
square.transparency = 0.5;
cout << square.str();
// 이제 square의 어떤 멤버든 접근 가능
square.resize(3);
하지만 모든 생성자를 한번에 편리하게 호출 하던 부분을 잃었다.
데커레이션을 완성하기 위해 ColoredShape와 TransparentShape에 생성자를 전달한다. 이 생성자들은 두 종류의 인자를 받는다. 첫번째 인자들은 현재의 템플릿 클래스에 적용되는 것들이고 두번째 인자들은 부모 클래스에 전달될 제네릭 파라미터 팩이다.
template <typename T> struct TransparentShape : T{
uint8_t transparency;
template<typename...Args>
TransparentShape(const uint8_t transparency, Args ...args)
: T(std::forward<Args>(args)...), transparency{ transparency }{}
//...
}; // ColoredShape에서도 동일하게 구현
전체 코드 :
더보기
#include <iostream>
#include <sstream>
using namespace std;
struct Shape {
virtual string str() const = 0;
};
struct Circle : Shape {
float radius;
Circle(){}
explicit Circle(const float radius)
: radius{ radius } {}
void resize(float factor) { radius *= factor; }
string str() const override {
ostringstream oss;
oss << "A circle of radius " << radius;
return oss.str();
}
};
struct Square : Shape {
float size;
Square(){}
explicit Square(const float size)
: size{ size } {}
void resize(float factor) { size *= factor; }
string str() const override {
ostringstream oss;
oss << "A square with side " << size;
return oss.str();
}
};
template <typename T> struct ColoredShape : T {
static_assert(is_base_of<Shape, T>::value,
"template argument must be a Shape");
string color;
ColoredShape(){}
template <typename...Args>
ColoredShape(const string& color, Args ...args)
: T(std::forward<Args>(args)...), color{ color }{}
// 여기서 베이스 클래스의 소멸자를 호출할 수는 없다.
// 왜냐면 소멸자를 알 수가 없기 때문이다.
string str() const override {
ostringstream oss;
oss << T::str() << " has the color " << color;
return oss.str();
}
};
template <typename T> struct TransparentShape : T {
static_assert(is_base_of<Shape, T>::value,
"template argument must be a Shape");
uint8_t transparency;
TransparentShape(){}
template<typename...Args>
TransparentShape(const uint8_t transparency, Args ...args)
: T(std::forward<Args>(args)...), transparency{ transparency }{}
string str() const override {
ostringstream oss;
oss << T::str() << " has "
<< static_cast<float>(transparency) / 255.f * 100.f
<< "% transparency";
return oss.str();
}
};
int main() {
// 디폴트 생성자가 없으면 동작하지 않는다.
ColoredShape<TransparentShape<Square>> square{ "blue" };
square.size = 2;
square.transparency = 50;
cout << square.str() << endl;
square.resize(3);
ColoredShape<TransparentShape<Square>> sq = { "red", 51, 5 };
cout << sq.str() << endl;
// 출력결과 "A square with side 5 has 20% transparency has the color red"
return 0;
}
'Design Pattern > Modern C++ 디자인패턴' 카테고리의 다른 글
9-1. 데커레이터_동적 데커레이터 (0) | 2020.08.26 |
---|---|
8-2. 컴포지트_그래픽 객체의 그루핑 (0) | 2020.08.22 |
8-1. 컴포지트_배열에 기반한 속성 (0) | 2020.08.22 |
7-2. 브릿지_브릿지 패턴 (0) | 2020.05.18 |
7-1. 브릿지_Pimpl idiom (0) | 2020.05.18 |