前言
看到享元模式,想到了在工作时写的地图编辑器就可以使用此模式去优化一下内存,享元模式主要减少创建对象数量,以减少内存占用,简直优化游戏内存利器啊。
1. 一般地图数据格式
一般2D地图都是使用二维数组去表示的,数组里面存着结构体,结构体里的字段可能碰撞信息,图片信息等等,一般地图资源的情况,我们用代码模拟一下即可,具体代码如下:
public enum CollisionType:byte
{
Stop,//完全阻挡
Walk,//所以通过
Fly,//只能飞
Swim,//可游可飞
}
public struct MapData
{
private uint ImgLib;
private uint ImgIndex;
private byte PlaySpeed;
private byte FrameCount;
private CollisionType CollisionType;
}
这样再定义一个MapData的二维数组即可,MapData[,] MapArray = new MapData[MapInfo.Width, MapInfo.Height];这样就搞定了,主要拿着这个二维数组的数据拿去渲染地图。但是!!!地图上可能有大量重复利用的图片资源,比如有相同的树,相同的草地,也就是说MapData的二维数组里可能存在大量相同的数据,多余的占领着内存空间,所以可以使用享元模式优化这个二维数组。
2.享元模式优化地图大小
享元模式是把资源存到哈希表里,然后一个资源有唯一对应的Key,这样就不需要创造重复的对象了,具体实现代码如下:
public class MapFactory
{
public uint ResNum;
public Dictionary<uint,MapData> MapDataSet;
public MapFactory()
{
ResNum = 0;
MapDataSet = new Dictionary<uint, MapData>();
}
public uint GetMapKey(MapData tmpData)
{
foreach (var mapData in MapDataSet)
{
if (mapData.Value.Equals(tmpData))
return mapData.Key;
}
MapDataSet.Add(ResNum,tmpData);
ResNum = ResNum + 1;
return ResNum - 1;
}
public MapData? GetMapValue(uint index)
{
try
{
MapData tmpData;
MapDataSet.TryGetValue(index, out tmpData);
return tmpData;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
经过以上的处理,数组变成了int[,] MapArray = new int[MapInfo.Width, MapInfo.Height];。当我们需要具体数据渲染时,调用GetMapValue即可,然后读取地图文件时通过GetMapKey去把地图二维数组构建出来。享元模式确实做到了优化内存的功能,但是它也是有挺多缺点的,接下是时候总结一下享元模式的优缺点和使用场景。
总结
1.享元模式的优缺点
优点:大大减少对象的创建,降低系统的内存,使重复利用率提高,减少对象数量从而改善应用所需的对象结构的方式。
缺点:虽然降低内存的使用,但是性能方面增加消耗,因为增加了哈希表添加,查询等操作。还有创建的对象状态会变化时就不能使用。比如很多玩家喜欢玩剑客,剑客这个角色开始的状态是一样的,但是玩家们让角色穿戴不同装备等等一系列操作就发生了变化。
2.享元模式的使用场景
1)优化游戏地图的内存占用。
2)多线程池的底层原理。