On this page
article
Separating Commonality and Variability: Template, Strategy, PBD
Template Method
개념 알고리즘의 전체 흐름은 고정하고, 일부 단계의 구현만 서브클래스에 위임하는 방식.
- 공통적인 처리 로직은 베이스 클래스에 둠
- 변경 가능한 부분은 가상 함수로 두고 서브클래스에서 오버라이딩
- 재정의용 함수는 외부에서 호출될 필요가 없으므로
protected
로 지정
Strategy
개념 변하는 부분을 별도의 클래스로 분리하여 유연하게 교체할 수 있도록 하는 방식.
- 변화하는 부분을 가상 함수로 분리하거나
- 아예 다른 클래스로 분리하여 주입
예시
struct IValidator {
virtual bool validate(const std::string& data, char c) = 0;
virtual bool iscomplete(const std::string& data) { return true; }
virtual ~IValidator() {}
};
class DigitValidator : public IValidator {
int count;
public:
DigitValidator(int count = 9999) : count(count) {}
bool validate(const std::string& data, char c) override {
return data.size() < count && isdigit(c);
}
bool iscomplete(const std::string& data) override {
return count != 9999 && data.size() == count;
}
};
class Edit {
std::string data;
IValidator* val = nullptr;
public:
void set_validator(IValidator* p) { val = p; }
};
Template vs Strategy
기준 | Template Method | Strategy |
---|---|---|
정책 변경 | 고정 | 런타임에 교체 가능 |
데이터 접근 | 내부 멤버 접근 용이 | 상대적으로 복잡 |
재사용성 | 재사용 어려움 | 재사용성 높음 |
Policy-Based Design
개념 전략 패턴과 유사하나, 가상 함수를 제거하여 성능을 극대화한 패턴. C++ STL에서 많이 사용.
특징
- 실행 시간 오버헤드(가상함수 호출, vtable 등)를 제거
- 템플릿을 이용한 정책 삽입 → 인라인 치환 가능
사용 예시: allocator
template<typename T, typename Alloc = std::allocator<T>>
class Vector {
T* buff;
std::size_t size;
std::size_t capacity;
Alloc ax;
};
장단점 요약
항목 | 설명 |
---|---|
장점 | 실행 시점 오버헤드 없음, 인라인 치환 가능 |
단점 | 런타임 교체 불가 (컴파일 시 결정됨) |
사용 적합 | 정책이 자주 바뀌지 않는 경우 |
결론
- Template Method: 내부 멤버 접근이 쉽고 알고리즘 흐름 고정에 유리
- Strategy: 런타임 교체 가능성 높고 유연성 확보
- Policy-Based Design: 성능 최적화가 필요한 경우에 적합
// 예시: 정책 기반 설계 (Policy-Based Design)
template<typename Alloc>
class Container {
Alloc alloc;
};
이처럼 공통성과 가변성을 분리함으로써 유지보수성과 유연성을 모두 확보 가능.