Design Patterns/Structural Patterns

Decorator Pattern (C++)

개발새발 2019. 7. 21. 20:28
반응형

Decorator Pattern (C++)

목적

상황과 용도에 맞게객체에 동적으로 새로운 책임을 추가할 수 있다. OCP를 잘 나타내는 패턴으로 기능 확장이 필요할 때 기존 코드 수정 없이 확장이 가능한 구조이다.

그러나 단점으로는 데코레이터가 증가할 수록 작은 규모의 객체들이 많이 생기게 된다.

 

https://zetawiki.com/wiki/Decorator_%ED%8C%A8%ED%84%B4

사용 시나리오

  • 위젯을 그리는(Draw)하는 프로그램을 만든다고 가정한다.
  • 여러가지 위젯중 캘린더 위젯을 만들고 위젯은 Scroller, Boarder로 구성할 수 있다.

[Component]

동적으로 추가할 객체들의 인터페이스 역할을 한다.

 

 

class WidgetComponent {
public:
    virtual void Draw() = 0;
};

[ConcreteComponent]

제공할 서비스의 베이스가 되는 컴포넌트를 정의한다. (예 여러 위젯중 캘린더 위젯)

 

class CalendarWidget: public WidgetComponent {
public:
    virtual void Draw() {
        cout<<"Draw Window"<<endl;
    }
};

[Decorator]

Component객체에 대한 참조자를 관리(인스턴스 변수로 소유)하면서 Component에 정의 된 인터페이스를 만족하도록 인터페이스를 정의한다.

 

class Decorator: public WidgetComponent {
public:
    Decorator(WidgetComponent* comp): component(comp){};
    
    virtual void Draw() {
        component->Draw();
    }
    
private:
    WidgetComponent* component;
};

[ConcreteDecorator]

Component에 추가할 내용을 구체적으로 구현한다. (예 캘린더 위젯에 들어갈 Scroll, Board 등)

class BorderDecorator: public Decorator {
public:
    BorderDecorator(WidgetComponent* comp)
    :Decorator(comp){}
    
    virtual void Draw() {
        Decorator::Draw();
        DrawBoarder();
    }
    
private:
    void DrawBoarder() {
        cout<<"Draw Boarder"<<endl;
    }
};


class ScrollDecorator: public Decorator {
public:
    ScrollDecorator(WidgetComponent* comp)
    :Decorator(comp){}
    
    virtual void Draw() {
        Decorator::Draw();
        DrawScroll();
    }
    
private:
    void DrawScroll() {
        cout<<"Draw Scroll"<<endl;
    }
};

 

[사용 예]

 

int main(int argc, const char * argv[]) {
    WidgetComponent* widget = new CalendarWidget();
    widget = new BorderDecorator(widget);
    widget = new ScrollDecorator(widget);
    
    widget->Draw();
    
    return 0;
}

 

실행결과

Draw Window

Draw Boarder

Draw Scroll

반응형