Policy class

Policy class example 입니다.

#include <iostream>

using namespace std;

template<class T>
struct OpCreateNew
{
public:
    T* create() 
    { 
        cout << "Calling new" << endl;
        return new T; 
    }

protected:
    ~OpCreateNew() { }
};

template<class T>
struct OpCreateMalloc
{
public:
    T* create() 
    { 
        cout << "Calling malloc" << endl;
        T* result = static_cast<T*>(std::malloc(sizeof(T)));
        return result;
    }

protected:
    ~OpCreateMalloc() { }
};


template 
<
    class T, 
    template<class> class Creator
>
class Foo:public Creator<T>
{
public:
    Foo():storage_(this->create()) { }

protected:
    T* storage_;
};


int main()
{
    Foo<int, OpCreateNew> f1;
    Foo<int, OpCreateMalloc> f2;
    return 0;
}

코드에서 언급할 부분은 3가지입니다.

  1. protected 로 선언된 destructor는 f1 이나 f2를 Creator<T> 로 받아서 delete 하는 것을 막기 위해서 사용되었습니다.
  2. storage_(this->create()) 와 같은 this의 사용은 C++에서 기본적으로 템플릿 부모 클래스의 메소드 호출은 그런 메소드가 존재하지 않는다고 가정하기 때문에 필요합니다.
  3. template<class> class Creator과 같은 표현은 Creator가 템플릿임을 표시하기 위한 template template parameter입니다. (템플릿으로 정의된 템플릿 파라미터라는 말입니다.)

Modern C++ Design 1장의 내용을 그냥 코딩해 봤습니다. Policy Class라는 것은 말하자면 C++의 템플릿을 사용해서 GoF의 strategy 패턴을 구현한 것처럼 보입니다. 하지만 제 생각에 Strategy 패턴과는 다음과 같은 내용이 다릅니다.

  1. Strategy 패턴은 전략을 적용함에 있어서 인터페이스와 virtual method 호출에 의존하지만, Policy class 방식은 템플릿을 사용한 코드 생성에 의존합니다.
  2. Strategy 패턴은 후에 코드를 수정할 필요가 있을 때, 클래스 생성 부분에 인자로 주어지는 클래스명을 수정해야하지만, Policy class 방식은 템플릿 인자를 수정해야합니다.
  3. Strategy 패턴의 타입 안정성에 대한 검사는 동적이지만, Policy class 방식은 정적이며 컴파일시에 완료됩니다.
  4. Strategy 패턴에서는 정의된 메소드가 모두 상속되며 컴파일과 실행시에 항상 존재하지만, Policy class는 템플릿에 의존하므로 인해 Policy 가 정의하고 있는 메소드 들은 사용될 때에만 instantiation 이 완료됩니다.

Similar Posts:

Post a Comment

Your email is never published nor shared.