(C++ : Design-pattern) Decorator Pattern

Posted by : at

Category : Cpp   Design-pattern


Decorator 패턴

  • 실행 시간에 객체에 기능을 추가
  • 객체에 동적으로 새로운 서비스를 추가
  • 기능 추가를 위해 서브 클래스를 사용하는 것 보다 융통성 있는 방법을 제공
#include <iostream>
using namespace std;

class SpaceCraft
{
    int color;
    int speed;
public:
    void Fire() { cout << "Space Craft : ------------" << endl; }
};

int main()
{
    SpaceCraft sc;
    sc.Fire();
}
// 상속을 써보자.
class LeftMissile : public SpaceScraft
{
public:
     void Fie()
     {
         SpaceCraft::Fire();
         cout << "Left Missile : >>>>>>>>>>>>>>>>" << endl;
     }
};

int main()
{
    SpaceCraft sc;
    sc.Fire();

    // 문제는 위의 sc와는 전혀 관계없는 새로운 오브젝트가 생긴것이다.
    LeftMissile lm;
    lm.Fire();
}
// 구성(Composition)을 통한 기능추가
class LeftMissile
{
    SpaceCraft* craft;
public:
    LeftMissile(SpaceCraft* p) : craft(p) {}
    void Fire()
    {
        craft->Fire();
        cout << "Left Missile : >>>>>>>>>>>>>>>>" << endl;
    }
};

int main()
{
    SpaceCraft sc;
    sc.Fire();

    LeftMissile lm(&sc);
    lm.Fire();
}
  • 상속에 의한 기능추가 : 클래스에 추가, 코드 작성시 기능 추가 가능
  • 구성에 의한 기능추가 : 객체에 추가, 실행시간에 기능 추가 가능
class RightMissile
{
    SpaceCraft* craft;
public:
    RightMissile(SpaceCraft* p) : craft(p) {}
    void Fire()
    {
        craft->Fire();
        cout << "Right Missile : >>>>>>>>>>>>>>>>" << endl;
    }
};

int main()
{
    SpaceCraft sc;
    sc.Fire();

    LeftMissile lm(&sc);
    lm.Fire();

    RightMissile rm(&sc);       // ??? -> lm을 주소로 보내야하지 않나? -> 현재는 불가능
    rm.Fire();
}
struct Component
{
    virtual void Fire() = 0;
    virtual ~Component() {}
};

class SpaceCraft : public Component
{
    int color;
    int speed;
public:
    void Fire() { cout << "Space Craft : ------------" << endl; }
};

class LeftMissile : public Component
{
    Component* craft;
public:
    LeftMissile(Component* p) : craft(p) {}
    void Fire()
    {
        craft->Fire();
        cout << "Left Missile : >>>>>>>>>>>>>>>>" << endl;
    }
};

class RightMissile : public Component
{
    Component* craft;
public:
    RightMissile(Component* p) : craft(p) {}
    void Fire()
    {
        craft->Fire();
        cout << "Right Missile : >>>>>>>>>>>>>>>>" << endl;
    }
};

int main()
{
    SpaceCraft sc;
    sc.Fire();

    LeftMissile lm(&sc);
    lm.Fire();

    RightMissile rm(&lm);       // ok
    rm.Fire();
}

조금 더 진화해보자.

struct IDecorator : public Component
{
    Component* craft;
public:
    IDecorator(Component* p) : craft(p) {}
    void Fire() { craft->Fire(); }
};

class LeftMissile : public IDecorator
{
public:
    LeftMissile(Component* p) : IDecorator(p) {}
    void Fire()
    {
        IDecorator::Fire();
        cout << "Left Missile : >>>>>>>>>>>>>>>>" << endl;
    }
};

class RightMissile : public IDecorator
{
public:
    RightMissile(Component* p) : IDecorator(p) {}
    void Fire()
    {
        IDecorator::Fire();
        cout << "Right Missile : >>>>>>>>>>>>>>>>" << endl;
    }
};

About Taehyung Kim

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

Star
Useful Links