游戏和网站开发不一样的地方在于,游戏对象通常是常驻在内存的。
当用户第一次登录的时候会一次性把玩家某个模块的数据全部读到内存里面,以后除了维护之外,内存中的数据都不会释放掉,玩家的数据存储则是定时批量地写入数据库。
经常要为玩家角色存储一些数据,比如神器,装备,时装,他们都是GameObject,就像这样:
public abstract class GameObject {
public enum DataState {
......
};
protected DataState curDataState = DataState.dsModify;
......
protected abstract int saveInsert();
protected abstract int saveDelete();
protected abstract int saveModify();
public abstract long getId();
public abstract void setAllModifyState();
public abstract void clearModifyState();
public abstract int deleteObject();
@JsonIgnore
protected boolean bSaveDBFlag = false;
@JsonIgnore
public boolean isSaveDBFlag() {
return bSaveDBFlag;
}
@JsonIgnore
public String getClassFlag() {
......
}
@JsonIgnore
private SqlExecuter getExecuter() {
......
}
/**
* 标记存库成功,设置对应的状态
*/
public final void saveDBSuccessed() {
......
}
/**
* 如果所存储的Manager容器默认IdMap有记录数组Index索引,那么就可以通过这个index索引来快速找到对象在ArrayList中的位置
*/
public int arrayIndex = 0;
public void autoSave() {
......
}
public void saveToDB() {
......
}
/**
* 计划存储
*
* @return
*/
public void saveToDBInPlan() {
......
}
public void realSaveToDB() {
......
}
/**
* 把对象放入到执行任务中
*/
public int AddObjToTask() {
......
}
......
}
每一个角色都要有自己的GameObject,也就有自己的容器GameObjectMgr,每一个角色都有自己的GameObjectMgr,存储所有角色的游戏物品的类,可以设计为GameDataHolder:
/**
* 享元模式
*
* @author 林子豪
*
*/
public class GameDataHolder {
//manager的class,角色id,manager
public static Map<Class<?>, Map<Long, Object>> roleMap = new HashMap<>();
public static <T extends GameObjectMgr<?>> T getMgr(Class<T> clz, Long roleId, Supplier<T> mgrGenerator) {
Map<Long, Object> mgrMap = roleMap.get(clz);
if (mgrMap == null) {
mgrMap = new HashMap<>();
roleMap.put(clz, mgrMap);
}
Object t = mgrMap.get(roleId);
if (t == null) {
t = mgrGenerator.get();
}
return clz.cast(t);
}
public static <T extends GameObjectMgr<?>> T getMgr(Class<T> clz, Long roleId) {
Map<Long, Object> mgrMap = roleMap.get(clz);
if (mgrMap == null) {
mgrMap = new HashMap<>();
roleMap.put(clz, mgrMap);
}
Object t = mgrMap.get(roleId);
if (t == null) {
try {
t = clz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return clz.cast(t);
}
}
-
使用享元模式,而不是多个单例,代码量大大减少,符合单一职责原则。
-
java的Supplier<T>的惰性加载。
-
外部传入mgrGenerator对象,生成GameObjectMgr对象。
-
使用Class对象cast方法,防止对象转换时出现的警告。