(C++ : Design-pattern) Template Method, Strategy Pattern 비교

Posted by : at

Category : Cpp   Design-pattern


  1. 변하는 것을 가상 함수로 만들어서 파생클래스로 만들어 보는게 어떨까? -> Template method
  2. 변하는 것을 인터페이스화 해서 파생클래스로 만들어 보는게 어떨까? -> Strategy Composition

Template Method

우선 아래는 Template Method 예제이다.

// validation을 위한 인터페이스
struct IValidator
{
    virtual bool validate(string s, char c) = 0;
    virtual bool iscomplete(string s) { return = true; }
    virtual ~IValidator() {}
};

class Edit
{
    string data;
    IValidator* pVal = 0;
public:
    void setValidator(IValidator* p) { pVal = p; }

    string getData()
    {
        data.clear();
        while(1)
        {
            char c = getch();
            if(c == 13 &&
                 pVal == 0 || pVal->iscomplete(data)) break;

            if( pVal == 0 || pVal->validate(data, c) )      // validation을 위임한다.
            {
                data.push_back(c);
                cout << c;
            }
        }
        cout << endl;
        return data;
    }
};

class LimitDigitValidator : public IValidator
{
    int value;
public:
    LimitDigitValidator(int n) : value(n) {}
    virtual bool validate( string s, char c )
    {
        return s.size() < value && isgidit(c);
        // 이런식으로 변하는 부분을 함수화 했다.
    }

    virtual bool iscomplete(string s)
    {
        return s.size() == value;
    }
};

int main()
{
    Edit edit;
    LimitDigitValidator v(5);
    edit.setValidator(&v);
}

Template method

  • 장점은 정책을 중간에 변경할 수 있다.

Strategy 와 차이점?

Strategy Composition -> 상속 기반의 패턴들은 유연성이 떨어지고 실행 시간에 정책을 교체할 수 없다.(정책을 새로 만들어야한다.)

int main()
{
    // AddressEdit edit;
    newAddressEdit edit;        // 정책변경을 위해 새로운 클래스를 만들어야함.

    while(1)
    {
        string s = edit.getData();
        cout << s << endl;
    }
}

단, 정책의 재 사용성이 필요없을 경우 template method이 훨씬 유리하다.

  • template method : 상속을 통해 아에 재 정의
  • Strategy pattern : 필요한 부분만 교체교체

template method 정리

  • 템플릿 메소드에서 알고리즘의 골격을 정의
  • 알고리즘의 여러 단계중 일부는 서브 클래스에서 구현 -> 훅(hook) 메소드라 한다.
  • 알고리즘의 전반적 구조를 유지하면서 서브 클래스에서 특정 단계를 재지정한다.
class Shape
{
protected:
    virtual void DrawImp()      // hook method
    {
        cout << "Draw Shape" << endl;
    }
public:
    virtual void Draw() final
    {
        cout << "mutex lock" << endl;
        DrawImp();
        cout << "mutex unlock" << endl;
    }
    virtual Shape* Clone() { return new Shape(*this); }
};

class Rect : public Shape
{
    virtual void DrawImp()      // hook method
    {
        cout << "Rect Draw Shape" << endl;
    }
};

Strategy pattern 정리

  • 알고리즘의 군을 정의 하고, 각각을 캡슐화 해서 교환해서 사용할 수 있도록 만든다.
  • Strategy 패턴을 활용하면 클라이언트와 독립적으로 알고리즘을 변경/생성 할 수 있다.
struct IValidator
{
    virtual bool validate(string s, char c) = 0;
    virtual bool iscomplete(string s) { return = true; }
    virtual ~IValidator() {}
};

class Edit
{
    string data;
    IValidator* pVal = 0;
public:
    void setValidator(IValidator* p) { pVal = p; }

    string getData()
    {
        data.clear();
        while(1)
        {
            char c = getch();
            if(c == 13 &&
                 pVal == 0 || pVal->iscomplete(data)) break;

            if( pVal == 0 || pVal->validate(data, c) )      // validation을 위임한다.
            {
                data.push_back(c);
                cout << c;
            }
        }
        cout << endl;
        return data;
    }
};

class LimitDigitValidator : public IValidator
{
    int value;
public:
    LimitDigitValidator(int n) : value(n) {}
    virtual bool validate( string s, char c )
    {
        return s.size() < value && isgidit(c);
    }

    virtual bool iscomplete(string s)
    {
        return s.size() == value;
    }
};

int main()
{
    Edit edit;
    LimitDigitValidator v(5);
    edit.setValidator(&v);
}

About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links