경량 패턴

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_(1false, GRASS_TEXTURE),
        hillTerrain_(3false, HILL_TEXTURE),
        riverTerrain_(2true, 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