프로그래밍 기술/Escort GoF의 디자인 패턴

9. 장식자 패턴(Decorator Pattern) [Escort GoF의 디자인 패턴]

언제나휴일 2016. 4. 4. 13:57
반응형

9. 장식자 패턴(Decorator Pattern)

 

9.1 개요

 

 프로그래밍하다 보면 너무 다양한 형태로 기능을 확장해야 할 경우가 발생합니다. 예를 들면 여러 종류의 단위 기능이 있고 이들을 조합해서 사용할 경우입니다. 사진에 원 장식을 하고 여기에 사각형 장식을 하고 여기에 삼각형 장식을 하는 등의 작업을 반복할 수 있는 경우처럼 말이죠. 이 같은 경우에 단위 기능들에 대한 조합된 기능을 수행할 수 있는 개체 형식들을 정의하기 위해서는 무수히 많은 수의 파생 클래스를 정의해야 합니다. 이때 장식자 패턴을 사용하면 장식자 개체에서 필요한 단위 기능을 하는 형식 개체를 포함을 시키는 것으로 이를 해결할 수 있습니다.

 

 이 같은 경우에 장식자 패턴은 단위 기능을 수행하는 형식과 장식자 형식을 정의하고 일반화하여 기반 클래스를 제공합니다. 이때 기반 클래스를 컴포넌트라 부르며 장식자에 멤버로 컴포넌트 형식을 포함합니다. 장식자 개체는 포함된 내부 개체가 어떠한 기능을 수행하는가에 따라 실제 수행할 수 있는 기능이 달라집니다. , 사용자는 장식자를 사용하는 것처럼 보이지만 실제 동작은 장식자 내부에 포함된 개체의 기능이 수행되는 것입니다. 여러 단위 기능을 수행하게 하려면 장식자 개체에 각 기능을 수행하는 형식 개체를 포함하면 됩니다. 물론, 같은 단위 기능을 반복해서 사용하고자 한다면 같은 형식의 장식자 개체를 여러 개 만들어서 포함하면 됩니다.

 

 한글이나 MS 워드와 같은 문서 편집기에서는 문서에 포함할 수 있는 요소들을 장식자 패턴을 적용하고 있습니다.

 

 

 

 

 

 

9. 2 시나리오

 

 지난주에는 청주 야구장으로 놀러 갔습니다. 저는 국내로 복귀한 박찬호의 응원 타월을 구입하였고 아내에게 사진을 찍어달라고 하였습니다. 그리고 아들 혁재에게 카메라를 주었습니다. 아들 혁재는 경기보다는 선수들의 사진과 응원하는 광경을 찍는 것에 신이 났습니다.

 

 좋은 하루를 보냈다고 생각을 했는데 집에 도착한 후에 컴퓨터에 사진을 옮기는 과정에서 혁재의 표정이 밝지 않습니다. 열심히 찍은 사진들에 색온도와 명도 값이 적절치 않았거든요. 아마도 제 사진을 찍으면서 설정한 것을 바꾸지 않고 그냥 찍었나 봅니다.

 

 저는 혁재에게 EH Camera 사이트에 방문하여 사진 편집 소프트웨어를 다운받고 바로잡아 줄 테니 너무 걱정하지 말라고 하였습니다. 그 말을 듣고도 혁재는 여전히 풀이 죽어 있었습니다. 덕분에 저는 밤 새 수정 작업을 하였습니다.

 

 수정 작업을 많이 해 보지 않아서 색온도를 조절했다가 명도 값을 조절하고 다시 색온도를 조절하고 채도 값을 조절하는 등의 여러 작업을 반복해서 하다 보니 밤은 그리 길지 않았습니다. 아침이 밝아오는 무렵에 저는 잠이 들었고 일어나 보니 머리맡에 쪽지가 하나 있더군요.

 

 "아빠 짱! 사랑해요. ♡뿌잉~ 뿌잉~"


장식자 패턴



AboutDecorator.zip


//common.h

#pragma once

 

#pragma warning (disable:4996)

#include <iostream>

 

using std::cout;

using std::endl;

#include <vector>

using std::vector;

#include <string>

using std::string;

 

#include <iomanip>

using std::ios;

#include <algorithm>

 

//Picture.h

#pragma once

#include "common.h"

 

class Picture

{

             int tone;

             int brightness;

             int saturation;

public:

             Picture(int tone,int brightness,int saturation);                   

             void ChangeTone(int tone);

             void ChangeBrightness(int brightness);

             void ChangeSaturation(int saturation);

             void View();

};

 

//Picture.cpp

#include "Picture.h"

 

Picture::Picture(int tone,int brightness,int saturation)

{

             this->tone = tone;

             this->brightness = brightness;

             this->saturation = saturation;

}

 

 

void Picture::ChangeTone(int tone)

{

             this->tone += tone;

}

void Picture::ChangeBrightness(int brightness)

{

             this->brightness += brightness;

 

}

void Picture::ChangeSaturation(int saturation)

{

             this->saturation += saturation;

}

 

void Picture::View()

{

             cout<<"색조:"<<tone<<" 명도:"<<brightness<<" 채도:"<<saturation<<endl;

}

 

//Compensator.h

#pragma once

 

#include "Picture.h"

class Compensator

{

public:   

             virtual void Change(Picture *picture,int tone,int brightness,int saturation)=0;

};

 

//BrightnessCompensator.h

#pragma once

#include "Compensator.h"

 

class BrightnessCompensator :

             public Compensator

{

public:

             virtual void Change(Picture *picture,int tone,int brightness,int saturation)

             {

                           picture->ChangeBrightness(brightness);

             }

};

 

//SaturationCompensator.h

#pragma once

#include "Compensator.h"

 

class SaturationCompensator :

             public Compensator

{

public:

             virtual void Change(Picture *picture,int tone,int brightness,int saturation)

             {

                           picture->ChangeSaturation(saturation);

             }

};

 

//ToneCompensator.h

#pragma once

#include "compensator.h"

 

class ToneCompensator :

             public Compensator

{

public:

             virtual void Change(Picture *picture,int tone,int brightness,int saturation)

             {

                           picture->ChangeTone(tone);

             }

};

 

//MultiCompensator.h

#pragma once

#include "Compensator.h"

#include "common.h"

typedef vector<Compensator *> Compensators;

typedef vector<Compensator *>::iterator CIter;

class MultiCompensator :

             public Compensator

{

             Compensators compensators;

public:

             virtual void Change(Picture *picture,int tone,int brightness,int saturation)

             {

                           CIter seek = compensators.begin();

                           CIter end = compensators.end();

 

                           for( ;seek != end; ++seek)

                           {

                                        (*seek)->Change(picture,tone,brightness,saturation);

                           }                         

             }

             void AddCompensator(Compensator *compensator)

             {

                           compensators.push_back(compensator);

             }

};

 

//Demo.cpp

#include "ToneCompensator.h"

#include "BrightnessCompensator.h"

#include "SaturationCompensator.h"

#include "MultiCompensator.h"

 

int main()

{           

             Compensator *compensator = new MultiCompensator();

             Picture *picture = new Picture(100,100,100);

 

             Compensator *tonecom = new ToneCompensator();

             Compensator *brightcom = new BrightnessCompensator();

             Compensator *saturcom = new SaturationCompensator();

 

             MultiCompensator *mc = dynamic_cast<MultiCompensator *>(compensator);

 

             mc->AddCompensator(tonecom);

             mc->AddCompensator(brightcom);

             mc->AddCompensator(saturcom);

 

             compensator->Change(picture,20,15,12);

             picture->View();

 

             delete saturcom;

             delete brightcom;

             delete tonecom;

             delete picture;

             delete compensator;

             return 0;

}

 

 

IT 전문가로 가는 길 Escort GoF의 디자인 패턴
국내도서
저자 : 장문석
출판 : 언제나휴일 2013.04.01
상세보기


 

반응형