2024. 3. 15. 18:33ㆍ디자인패턴
경량패턴 : 공유 sharing 을 통해 많은 수의 소립 fine-grained 객체들을 효과적으로 지원한다.
게임에서 우리가 화면을 가득 채운 빽빽한 숲을 볼 때 그래픽스 프로그래머는 수백만개의 폴리곤을 본다
나무마다 필요한 데이터가 다음과 같이 있다고 가정해보자
- 줄기, 가지, 잎의 형태를 나타내는 폴리곤 메시
- 나무 껍질과 잎사귀 텍스쳐
- 필드에서의 위치와 방향
- 크기와 음영 등 값 조절이 가능한 매개변수
1
2
3
4
5
6
7
8
9
10
11
|
class Tree {
private:
Mesh mesh;
Texture bark_;
Texture leaves_;
Vector position_;
double height_;
double thickness_ ;
Color barkTint_;
Color leafTint_;
};
|
cs |
숲을 표현 할 때 나무같은 개체들은 보통 복사된 형태로 수십개씩 존재하는데
나무 하나하나 개체의 모든 정보들을 여러번 메모리에 올리는것은 굉장한 공간낭비다.
모든 나무가 공통으로 공유하는 데이터를 뽑아내 새로운 클래스를 만들어
공유 할 수 있다면 많은 데이터가 절약될것이다.
1
2
3
4
5
6
7
|
class TreeModel
{
private:
Mesh mesh_; //메시
Texture bark_; //나무껍질
Texture leaves_; //잎
};
|
cs |
이 속성들은 모든 나무가 공통으로 가지는 속성이다.
1
2
3
4
5
6
7
8
9
10
11
|
class Tree {
private:
TreeModel* model_;
Vector position_;
double height_;
double thickness_j;
Color barkTint_;
Color leafTint_;
};
|
cs |
각 나무 인스턴스는 공통된 속성을 가지고
이 속성을 가지고 있는 클래스 model을 참조하기만 하고
tree클래스에는 각 나무마다 다른 상태값을 가지는 정보만 남겨두면 된다.
이런식으로 메모리를 아낄 수 있다.
경량패턴은 어떤 객체의 개수가 너무 많을 때 좀 더 가볍게 만들기 위해 사용한다.
경량 패턴을 구현하는 방법은 간단하다.
먼저 모든 객체의 데이터 값이 같아 공유 할 수 있는 데이터를 모은다 이러한 데이터를
GoF에서 고유상태라 한다
나머지 데이터는 인스턴스 별로 값이 다른 ex) 위치, 너비, 높이 등은 외부상태 (extrinsic state) 에 해당한다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Terrain
{
public:
Terrain(int movementCost, bool isWater, Texture texture) :
movementCost_(movementCost), isWater_(isWater),
texture_(texture) {}
int getMovementCost() const { return movementCost_; }
bool isWater() const { return isWater_; }
const Texture& getTexture() const { return texture_; }
private:
int movementCost_;
bool iswater_;
Texture texture_;
};
|
cs |
예를 들어 지형과 관련된 클래스는 이렇게 만들 수 있다.
이 지형이 물인지, 이동 비용은 어느정도인지 텍스쳐는 무엇인지는
모든 지형들은 다 가지고 있는 정보이므로 Terrian객체는 여러개 있을 필요가 없다.
1
2
3
4
5
6
7
|
class World
{
private:
Terrain tiles_[WIDTH][HEIGHT];
// 그 외...
};
|
cs |
다음과 같이 지형을 저장할 수 있다 이 지형을
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class World {
public:
World() :
grassTerrain_(1, false, GRASS_TEXTURE),
hillTerrain_(3, false, HILL_TEXTURE),
riverTerrain_(2, true, RIVER_TEXTURE) {}
private:
Terrain grassTerrain_;
Terrain hillTerrain_;
Terrain riverTerrain_;
// 그 외...
};
|
cs |
여러곳에서 사용되기 때문에 동적으로 할당하면 생명주기를 관리하기 어려우니
world 클래스에 저장하고
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
|
void World::generateTerrain() {
// 땅에 풀을 채운다.
for (int x = 0; x < WIDTH; x++)
{
for (int y = 0; y < HEIGHT; y++)
{
// 언덕을 몇 개 놓는다.
if (random(10) == 0)
{
tiles_[x][y] = &hillTerrain_;
}
else
{
tiles_[x][y] = &grassTerrain_;
}
}
}
// 강을 하나 놓는다.
int x = random(WIDTH).
for (int y = 0; y < HEIGHT; y++)
{
tiles_[x][y] = &riverTerrain_;
}
}
|
cs |
이렇게 다음과 같이 땅 위를 채울 수 있다.
경량 패턴을 사용하면 객체를 마구 늘리지 않으면서도 객체지향 방식의 장점을 취할 수 있다.
'디자인패턴' 카테고리의 다른 글
싱글턴 패턴 (Singleton Pattern) (1) | 2024.03.22 |
---|---|
프로토타입(Prototypical) 패턴 (0) | 2024.03.18 |
관찰자(Observer) 패턴 (0) | 2024.03.15 |
명령(command) 패턴 (0) | 2024.03.11 |
게임 구조에 대한 중요성 (0) | 2024.03.10 |