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

11. 플라이급 패턴(Flyweight Pattern) [Escort GoF의 디자인 패턴]

언제나휴일 2016. 4. 4. 14:04
반응형

11. 플라이급 패턴(Flyweight Pattern)

 

11.1 개요

 

 프로그램에서 개체가 많아지면 메모리가 많이 차지하게 됩니다. 이럴 때 메모리 효율을 높일 필요성이 있다면 무엇을 해야 할까요? 플라이급 패턴은 이러한 문제를 해결하기 위한 하나의 방법입니다. 플라이급 패턴은 개체의 멤버 필드 중에 각 개체가 반드시 갖고 있어야 할 멤버와 여러 개체가 공유해서 사용할 수 있는 멤버로 분리하는 작업에서부터 출발합니다. 공유해서 사용할 수 있는 멤버가 가질 수 있는 상태의 종류가 개체의 수보다 상대적으로 적다면 플라이급 패턴을 사용하여 메모리 효율을 높일 수 있습니다.

 

 플라이급 패턴에서는 공유해서 사용할 수 있는 상태들을 공유 풀에 형성합니다. 그리고 각 개체는 특정 상태를 참조합니다. 만약, 개체의 수가 상태의 수보다 상대적으로 많다고 한다면 개체마다 상태를 갖는 것보다 공유 풀에 있는 상태를 참조하는 것이 메모리 효율이 높겠죠.

 

11. 2 시나리오

 

 최근 들어 혁재는 여행을 다니며 사진을 찍는 것보다 사진을 바로잡는 것에 심취되어 있습니다. 그리고 조금씩 영상 처리에 관련된 프로그램을 작성하는 것에 관심을 두게 되었습니다. 덕분에 저와 혁재는 대화시간이 많이 늘어났고 친구처럼 지내게 되었습니다. 어제는 저에게 자신이 프로그램을 만들면서 해결하지 못하고 있는 것에 대한 질문을 하더군요.

 

 "아빠, 이번에 사진들을 관리하는 프로그램을 하나 만들고 있어요. 사진마다 어떤 Body와 어떤 렌즈를 사용했는지, 어떠한 조명에서 찍은 것인지 등을 알 수 있게 하려고요. 그런데 하다 보니 사진이 많아지면 너무 많은 메모리가 차지하게 되는 것 같아요."

 

 저는 잔잔한 미소를 지으며 책꽂이에서 'Escort GoF의 디자인 패턴'을 꺼내어 플라이급 패턴에 대해 살펴보라고 얘기를 해 주었습니다. 그리고 다음 날 혁재가 저에게 한마디 하더군요.

 

 "아빠! 다이어트~"

 

플라이급 패턴



AboutFlyweight.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>

 

#pragma warning(disable:4482)

 

//Meta.h

#pragma once

#include "common.h"

 

class Meta

{

public:

             enum BodyType{    EH_BA,    EH_BB,      EH_BC                  };

             enum LensType{                  EH_L1,                  EH_L2,                    EH_L3                  };

             enum LightType{    LT_CLEAR,LT_CLOUDY,LT_LAMP          };

private:

             const BodyType body;

             const LensType lens;

             const LightType light;          

             static const string bodyname[EH_BC+1];

             static const string lensname[EH_L3+1];

             static const string lightname[LT_LAMP+1];

public:   

             Meta(BodyType body,LensType lens,LightType light);         

             BodyType GetBodyType()const;

             LensType GetLensType()const;

             LightType GetLightType()const;

             bool IsEqual(BodyType _body,LensType _lens,LightType _light);

             void View()const;

};

 

typedef Meta::BodyType BodyType;

typedef Meta::LensType LensType;

typedef Meta::LightType LightType;

 

//Meta.cpp

#include "Meta.h"

 

 

const string Meta::bodyname[EH_BC+1]={"EH_BA","EH_BB","EH_BC"};

const string Meta::lensname[EH_L3+1]={"EH_L1","EH_L2","EH_L3"};

const string Meta::lightname[LT_LAMP+1]={"맑음","흐림","램프"};

Meta::Meta(BodyType body,LensType lens,LightType light):

             body(body),lens(lens),light(light)

{

}

 

BodyType Meta::GetBodyType()const

{

             return body;

}

LensType Meta::GetLensType()const

{

             return lens;

}

LightType Meta::GetLightType()const

{

             return light;

}

bool Meta::IsEqual(BodyType _body,LensType _lens,LightType _light)

{

             return (body==_body)&&(lens==_lens)&&(light==_light);

}

void Meta::View()const

{

             cout<<"Body:"<<bodyname[body];

             cout<<" Lens:"<<lensname[lens];

             cout<<" Light:"<<lightname[light]<<endl;

}

 

//MetaPool.h

#pragma once

#include "Meta.h"

typedef vector<Meta *> Metas;

typedef vector<Meta *>::iterator MIter;

class MetaPool

{

             Metas metas;

             static MetaPool singleton;

public:   

             static MetaPool *GetSingleton();

             Meta *MakeMeta(BodyType body,LensType lens,LightType light);

private:

             MetaPool();

             ~MetaPool(void);

};

 

//MetaPool.cpp

#include "MetaPool.h"

MetaPool MetaPool::singleton;

MetaPool *MetaPool::GetSingleton()

{

             return &singleton;

}

            

MetaPool::MetaPool()

{

}

MetaPool::~MetaPool(void)

{

             MIter seek = metas.begin();

             MIter end = metas.end();

 

             Meta *meta=0;

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

             {

                           meta = (*seek);

                           delete meta;                      

             }

}

Meta *MetaPool::MakeMeta(BodyType body,LensType lens,LightType light)

{

             MIter seek = metas.begin();

             MIter end = metas.end();

 

             Meta *meta=0;

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

             {

                           meta = (*seek);

                           if(meta->IsEqual(body,lens,light))

                           {

                                        return meta;

                           }

             }

             meta = new Meta(body,lens,light);

             metas.push_back(meta);

             return meta;

}

 

//PictureFile.h

#pragma once

 

#include "MetaPool.h"

class PictureFile

{

             const string name;

             Meta *meta;         

public:

             PictureFile(string name,BodyType body,LensType lens,LightType light);           

             void View()const;

};

 

//PictureFile.cpp

#include "PictureFile.h"

 

PictureFile::PictureFile(string name,BodyType body,LensType lens,LightType light):name(name)

{

             MetaPool *meta_pool = MetaPool::GetSingleton();

             meta = meta_pool->MakeMeta(body,lens,light);

}

 

 

void PictureFile::View()const

{

             cout<<"사진 이름:"<<name<<endl;

             meta->View();

}

 

//Demo.cpp

#include "PictureFile.h"

int main()

{

             PictureFile *pf = new PictureFile("사진1",BodyType::EH_BA,LensType::EH_L1,LightType::LT_CLEAR);

             PictureFile *pf2 = new PictureFile("사진2",BodyType::EH_BA,LensType::EH_L1,LightType::LT_CLEAR);

 

             pf->View();

             pf2->View();

 

             delete pf2;

             delete pf;

             return 0;

}

 

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


 

 

 

반응형