플라이 웨이트 패턴 --------------------------------------------------------------------------------------------------

  일반적으로 포인터나 주소값은 대부분 같은 것을 참조할 때가 많습니다.

  하지만 대부분의 객체가 이러한 포인터 값을 다수 가지고 있다면 메모리에 대한 부담이 커질수가 있습니다.

  그래서 하나의 자료구조에 포인터를 모아놓고 사용해야할 객체들이 그 정보들을 전역변수처럼 돌려쓰는 것이

  대표적인 것이 이미지에 대한 정보 입니다. 완전히 같은 이미지를 사용하는 2개의 객체가 있을때.

  굳이 2개의 이미지를 로딩하는 것이 아니라. 1개만 로딩한후 그것을 돌려쓰면 됩니다.


 

패턴적용 스토리 -----------------------------------------------------------------------------------------------

  당신에게 오브젝트 랜더에에 대한 임무가 내려졌습니다.

  오브젝트 랜더를 위해서는 이미지가 필요한데.

  각 오브젝트마다 이미지를 로딩해 봤더니 이미지에 대한 데이터부담이 너무 커졌습니다.

  그래서 당신은 플라이웨이트 패턴을 사용하여 만약 오브젝트들이 같은 이미지를 랜더한다면 그 이미지를 한번만 로딩하기로 결정했습니다.

 

uml -----------------------------------------------------------------------------------------------

 

 

플라이 웨이트패턴을 보면 오브젝트에서는 CFlyTexture에 있는 stl자료구조 안에 담긴 텍스처의 포인터를 가져와서 랜더를 합니다.

즉 프로토타입처럼 하나의 이미지를 다수의 오브젝트가 공유하여 사용하는 패턴입니다.

 

코드 -----------------------------------------------------------------------------------------------

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#pragma once
#include "include.h"
 
enum TEXTYPE
{
    TEXTYPE_SINGLE,
    TEXTYPE_MULTI,
};
 
enum FILENAME_COUNT
{
    FILENAME_COUNT_MAX = 100,
};
 
class Texture
{
protected:
    char    szName[FILENAME_COUNT_MAX];
 
public:
    virtual void LoadTexture(const char* pfilename) = 0;
    virtual void GetTexture(const int _iKey, const int TexCount = 0) = 0;
    virtual void Render(void) = 0;
};
 
class SingleTexture
    : public Texture
{
public:
    virtual void LoadTexture(const char* pfilename)
    {
        cout << pfilename << "텍스처 로딩" <<endl;
        strcpy_s(szName, pfilename);
    }
    virtual void GetTexture(const int _iKey, const int _TexCount = 0)
    {
        cout << szName << "텍스처 사용" <<endl;
    }
    virtual void Render(void)
    {
        cout << szName << "랜더" <<endl;
    }
 
public:
    SingleTexture(void) {}
    virtual ~SingleTexture(void) {}
};
 
class MultiTexture
    : public Texture
{
public:
    virtual void LoadTexture(const char* _pfilename)
    {
        cout << _pfilename << "폴더에 있는 모든 텍스처 로딩" <<endl;
        strcpy_s(szName, _pfilename);
    }
    virtual void GetTexture(const int _iKey, const int _TexCount)
    {
        cout << szName << " " << _TexCount << "텍스처 사용" <<endl;
    }
    virtual void Render(void)
    {
        cout << szName << " " << "애니메이션 랜더" <<endl;
    }
 
public:
    MultiTexture(void) {}
    virtual ~MultiTexture(void) {}
};
 
class CFlyTexture
{
private:
    map<const int, Texture*> m_mapTexture;
 
public:
    bool InsertTexture(const char* pfilename, const int iKey, const TEXTYPE& _eTexType)
    {
        map<const int, Texture*>::iterator Iter = m_mapTexture.find(iKey);
 
        if(Iter != m_mapTexture.end())
        { cout << "이미 추가된 텍스처 입니다" << endl; return true; }
 
        Texture* pTex;
 
        switch(_eTexType)
        {
        case TEXTYPE_SINGLE:
            {
                pTex = new SingleTexture;
                pTex->LoadTexture(pfilename);
                break;
            }
 
        case TEXTYPE_MULTI:
            {
                pTex = new MultiTexture;
                pTex->LoadTexture(pfilename);
                break;
            }
        }
 
        m_mapTexture.insert( map<const int, Texture*>::value_type(iKey, pTex) );
 
        return false;
    }
 
    void Init(void)
    {
        InsertTexture("지형지물0", 0, TEXTYPE_SINGLE);
        InsertTexture("지형지물1", 1, TEXTYPE_SINGLE);
        InsertTexture("지형지물2", 2, TEXTYPE_SINGLE);
        InsertTexture("지형지물3", 3, TEXTYPE_SINGLE);
        InsertTexture("몬스터1",  4, TEXTYPE_MULTI);
        InsertTexture("몬스터2",  5, TEXTYPE_MULTI);
        InsertTexture("플레이어", 6, TEXTYPE_MULTI);
 
        cout << endl;
    }
 
    Texture* GetTexture(const int iKey, const int TexCount = 0)
    {
        map<const int, Texture*>::iterator Iter = m_mapTexture.find(iKey);
 
        if(Iter == m_mapTexture.end())
        {
            cout << "텍스처가 없습니다" << endl;
            return NULL;
        }
 
        return Iter->second;
    }
 
    void Release(void)
    {
        map<const int, Texture*>::iterator Iter;
        for(Iter = m_mapTexture.begin(); Iter != m_mapTexture.end() ; ++Iter)
        {
            SAFE_DELETE(Iter->second);
        }
        m_mapTexture.clear();
    }
 
public:
    static CFlyTexture* m_Inst;
 
    static inline CFlyTexture* GetInst(void)
    {
        if(m_Inst == NULL)
            m_Inst = new CFlyTexture();
        return m_Inst;
    }
 
    static void DestroyInst(void)
    {
        SAFE_DELETE(m_Inst);
    }
 
private:
    CFlyTexture(void) {}
public:
    ~CFlyTexture(void) { Release(); }
};
 
CFlyTexture* CFlyTexture::m_Inst = NULL;
 
class CObject
{
private:
    int        TexNum;
 
public:
    void Render(void)
    {
        Texture* pTex = CFlyTexture::GetInst()->GetTexture(TexNum);
 
        if(pTex)
            pTex->Render();
    }
 
public:
    CObject(int _Tex) {TexNum = _Tex;}
    ~CObject() {}
};
 
// Flyweight.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
 
#include "stdafx.h"
#include "Flyweight.h"
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    CFlyTexture::GetInst()->Init();
 
    CObject* pTerrain0 = new CObject(0);
    CObject* pTerrain1 = new CObject(0);
    CObject* pTerrain2 = new CObject(1);
    CObject* pTerrain3 = new CObject(1);
    CObject* pMonster1 = new CObject(5);
    CObject* pMonster2 = new CObject(5);
    CObject* pMonster3 = new CObject(6);
    CObject* pPlayer   = new CObject(6);
 
    pTerrain0->Render();
    pTerrain1->Render();
    pTerrain2->Render();
    pTerrain3->Render();
    pMonster1->Render();
    pMonster2->Render();
    pMonster3->Render();
    pPlayer->Render();
 
    SAFE_DELETE(pTerrain0);
    SAFE_DELETE(pTerrain1);
    SAFE_DELETE(pTerrain2);
    SAFE_DELETE(pTerrain3);
    SAFE_DELETE(pMonster1);
    SAFE_DELETE(pMonster2);
    SAFE_DELETE(pMonster3);
    SAFE_DELETE(pPlayer);
 
    CFlyTexture::DestroyInst();
 
    return 0;
}

결과 -----------------------------------------------------------------------------------------------

 

Posted by JJOREG