一、定义
享元模式的定义: 运用共享技术来有效的支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。 享元模式主要包含以下角色: (1)抽象享元角色:所有具体享元类的基类,为具体享元规范需要实现的公共接口。 (2)具体享元角色:实现抽象享元角色中所规定的的接口。 (3)非享元角色:是不可以共享的外部状态。 (4)享元工厂角色:负责创建和管理享元角色。 其结构如下图所示: 该部分主要参考:享元模式(详解版),详情请点击该链接。
二、创建世界功能
如果我们希望创建一个游戏世界,那个可以能会有草地、丘陵、河流等很多地形。为了方便我们便基于区块来建立地形表:将世界划分为由微小区块组成的巨大网格,每个区块都被一种地形覆盖。 地形有以下特性: (1)移动开销 (2)是否可通行 (3)用于渲染的纹理。 由此,我们直接声明一个Terrain类,来保存这些数据。
在创建地形表的时候,如果我们选择1000*1000的地形,为每个位置都创建一个地形对象,便会占用大量的时间和内存(创建对象消耗的时间)。此外,我们可以发现这些创建的地形对象大部分都是重复的,其唯一的区别是地形在哪里。使用享元的术语来说,就是地形的所有状态都是“上下文无关的”。因此对于这些地形对象,我们进行共享。使用享元模式和不使用享元模式的性能差距还是很大的。
我们计算一下使用享元模式和不使用享元模式,64位系统下,100*100的地图的花销上的不同。 如: 共有部分介绍: Terrain类的三个属性分别为int、bool、char三种类型,其大小为:8字节。 创建一个Terrain对象,要0.01ms。 地形表中有10000个指针,总大小为:80000字节。 不使用享元模式: 创建10000个对象,占用内存:80000字节,时间消耗:100ms 使用享元模式: 由于本文中只有三种地形,因此只需3个对象,占用内存:24字节,时间消耗:0.03ms。
可以看见在100100的地图上,使用享元和不使用享元的差距都如此之大,如果是10001000的地图呢?10000*10000呢?
详情请点击以下链接: 游戏设计模式-享元模式
三、具体代码实现
3.1、前置准备
导入头文件和设置地图大小。
#include<iostream>
const int HEIGHT=10;
const int WIDTH=20;
3.2、地形类
声明三个属性特性,提供获取属性函数。具体享元类。
class Terrain{
public:
Terrain(int movementCost,bool isWater,const char texture):movementCost_(movementCost),isWater_(isWater),texture_(texture){}
int GetMovementCost(){return movementCost_;}
int IsWater() const {return isWater_;}
const char& GetTexture()const{return texture_;}
private:
int movementCost_;
bool isWater_;
char texture_;
};
3.3、世界类
初始化三种地形,随机生成世界地形,存储地形表。变相的享元工厂类。
class World{
public:
World():grassTerrain_(1,false,' '),
hillTerrain_(2,false,'^'),
riverTerrain_(3,true,'w')
{
GenerateTerrain();
}
void GenerateTerrain();
const Terrain& GetTile(int x,int y)const;
private:
Terrain grassTerrain_;
Terrain hillTerrain_;
Terrain riverTerrain_;
Terrain* tiles_[HEIGHT][WIDTH];
};
void World::GenerateTerrain(){
for(int i=0;i<HEIGHT;i++)
{
for(int j=0;j<WIDTH;j++)
{
if(rand()%10==0){
tiles_[i][j]=&hillTerrain_;
}
else{
tiles_[i][j]=&grassTerrain_;
}
}
}
int i=rand()%HEIGHT;
for(int j=0;j<WIDTH;j++)
{
tiles_[(i-1)%HEIGHT][j]=&riverTerrain_;
tiles_[i][j]=&riverTerrain_;
tiles_[(i+1)%HEIGHT][j]=&riverTerrain_;
}
}
const Terrain& World::GetTile(int x,int y) const{
return *tiles_[x][y];
}
3.4、主函数
输出游戏世界
int main(void)
{
World myWorld;
for(int i=0;i<HEIGHT;i++)
{
for(int j=0;j<WIDTH;j++)
{
std::cout<<myWorld.GetTile(i,j).GetTexture();
}
std::cout<<std::endl;
}
return 0;
}
四、输出结果
输出截图如下:
|