# 游戏中的享元模式

“使用共享以高效地支持大量地细粒度对象。”

比如森林，有很多树，成千上万个，这些树对象实例有很多共同的内容，比如 材质 纹理，所有树木通用的数据放到一个单独的类中

```cpp
class TreeModel
{
private:
    Mesh mesh_;
    Texture bark_;
    Texture leaves_;
};
```

树类

```cpp
class Tree
{
private:
    TreeModel* model_;
    Vector position_;
    double height_;
    double thickness_;
    Color barkTint_;
    Color leafTint_;
};
```

这样大量的树公用一个Model对象，节省了非常多的空间。在客户端GPU渲染中，就需要这样配合。

还有比如瓦片地图的地形,可以这样做。

```cpp
enum Terrain
{
    TERRAIN_GRASS,
    TERRAIN_HILL,
    TERRAIN_RIVER,
    // ...
};
```

```cpp
class World
{
private:
    Terrain tiles_[WIDTH][HEIGHT];
};
```

获取某个瓦片的有效数据

```cpp
int World:getMovementCost(int x, int y)
{
    switch(tiles_[x][y])
    {
        case TERRAIN_GRASS: return 1;
        case TERRAIN_HILL: return 3;
        case TERRAIN_RIVER: return 2;
        // ...
    }
}
bool World:isWater(int x, int y)
{
    switch(tiles_[x][y])
    {
        case TERRAIN_GRASS: return false;
        case TERRAIN_HILL: return false;
        case TERRAIN_RIVER: return true;
        // ...
    }
}
```

封装为地形类

```cpp
class Terrain
{
public:
　Terrain(int movementCost, bool isWater,
　　　　　Texture texture)
　: moveCost_(moveCost),
　　isWater_(isWater),
　　texture_(texture)
　{}

　int getMoveCost() const { return moveCost_; }
　bool isWater() const { return isWater_; }
　const Texture& getTexture() const 
　{ 
　return texture_; 
　}

private:
　int moveCost_;
　bool isWater_;
　Texture texture_;
};
```

然后在World中存 Terrain 的实例的地址就行了，多个位置公用一个实例

```cpp
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_;
  Terrain* tiles_[WIDTH][HEIGHT]; 
};
```

对World实现一些操作 如生成地形，获取某一位置瓦片，

```cpp
void World::generateTerrain()
{
　// Fill the ground with grass.


　for (int x = 0; x < WIDTH; x++)
　{
　　for (int y = 0; y < HEIGHT; y++)
　　{
　　// Sprinkle some hills.


　　　if (random(10) == 0)
　　　{
　　　　tiles_[x][y] = &hillTerrain_;
　　　}
　　　else
　　　{
　　　　tiles_[x][y] = &grassTerrain_;
　　　}
　　}
　}

　//Lay a river
　int x = random(WIDTH);
　for (int y = 0; y < HEIGHT; y++) {
　　tiles_[x][y] = &riverTerrain_;
　}
}


const Terrain& World::getTile(int x, int y) const
{
　return *tiles_[x][y]; 
}
```

就像这样使用

```cpp
int cost = world.getTile(2, 3).getMovementCost();
```

从空间和时间上看，开销都很低。
