字典设计(已废弃)

本文介绍了游戏服务器在启动时如何加载和组织静态数据,重点讨论了字典条目(entry)的概念,数据载体的选择,如lua、json、excel、数据库等,以及字典加载的两个关键步骤:数据读取和组织校验。字典条目在读取过程中经历解析、校验,最终组织成便于直接使用的结构。此外,还探讨了字典的统一管理和校验方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

  • 字典设计
    • 修改时间
    • 前言
    • 数据载体
    • 术语
    • 加载过程
      • 一、读取数据
      • 二、组织、校验
    • FAQ
    • 代码片段

字典设计

修改时间

文章可能会随时修改,慢慢完善。
2018-12-04 16:00

前言

游戏服务器在启动时,需要加载某些静态数据到内存之中,比如所有商品的配置数据(可能包含id、名称、价格等属性)。
这些静态数据在被加载后,会在内存中以某种形式呈现、组织和使用,在这里假设称它为"信息"。

见过很多种关于这种"信息"的命名,比如配置信息(config)、模型数据(model)、模板数据(template)、定义数据(def)。
在这些年中经历了以上的命名,最后还是选择了字典条目(dict)作为这种"信息"的命名。

数据载体

承载这些静态数据的载体有很多种,在选择上可能会基于开发语言或是团队喜好(方便、直观等)。

  1. 基于代码的格式,将数据组织成语言代码,比如lua、json、pike等,部分代码可以做成一种压缩形式。
  2. 基于excel,直接使用excel来保存数据。
  3. 基于数据库表。
  4. 基于文本文件,比如csv、lua、json等。
  5. 自定义编辑器,可能存成二进制或是文本格式。

术语

entry:字典条目,一般来说,一个字典条目对应一条记录。
dict:字典,某一类型的所有字典条目组成了一部字典,因此系统中很有可能会存在多部字典。

加载过程

当在系统中使用字典条目时,我们希望能直接获取和使用,不需要自己再做二次解析、转换等繁琐步骤。
为了达到以上目的,一般来说我们会将字典的加载过程分为两个步骤:

  1. 读取数据,可以认为是字典条目的处理。
  2. 组织、校验,可以认为是字典的内部结构组织和校验。

一、读取数据

  1. 从数据载体中读取数据记录,并将每条记录转换成对应的字典条目。
  2. 对记录中的特殊字段做解析,比如某些字符串其实是数组、键值对、枚举等。也就是说,字典条目中的字段完全是存放解析之后的数据,没有存放临时数据的字段。
  3. 调用自定义setter方法,处理一些特殊解析。
  4. 对字典条目中的某些字段做校验,比如最小值、最大值、非空等。
  5. 对记录中某些字段的解析,是有先后顺序的,比如有些字段的值依赖于其它字段的值。
  6. 以上步骤应该都是自动完成的。

二、组织、校验

  1. 对字典的内部结构进行组织。字典的内部结构可能是map(可能有顺序),也可能是array、table、其它结构,甚至可以没有结构。使用字典是为了更方便的获取字典条目或是数据。
  2. 定义特殊的获取字典条目的方法。比如我想直接获取前三名的奖励配置,只需要调用这个特殊方法就可以取到,不需要取出这三个字典条目,然后分别读奖励配置字段。
  3. 字典与字典之间可能是有依赖关系的,可能会使用其它字典条目。
  4. 字典整体的校验、处理。
  5. 以上步骤会有些部分重合。

FAQ

Q: 字典是放在各个模块中,还是统一存放在字典模块中?
A: 目前倾向放到字典模块中。字典并不涉及到特定业务逻辑,并且一个模块可能需要使用不同功能的字典数据。

Q: 使用哪种数据载体存放字典内容比较合适?
A: 这个还真得根据团队来看,目前在游戏服比较喜欢使用文本格式,查看比较直观,容易追踪版本变化,缺点是可能得写一套专门的导出工具。

Q: 怎么校验字典条目中某些字段的值?
A: 自己手写代码检查属于重复劳动了,可以使用注解(比如javax.validation),统一校验。

代码片段

仅仅用作参考演示。

/**
 * 数据字典基类。
 */
public abstract class Dict<T extends Entry> {
	/** 存放原始字典数据条目,不要直接使用它。 */
	protected TreeMap<Integer, T> primitiveEntries;

	/** 生成字典条目实例。 */
	public T newEntry() { ... }

	/** 待解析的数据字典文件。 */
	public abstract String getFilenames();
	
	/** 加载数据。 */
	public boolean load() { ... }

	/** 校验、组织。 */
	public abstract boolean process()
	...
}

/**
 * 数据字典条目基类。
 */
public abstract class Entry {
	/** 唯一标识。 */
	public int id;

	/** 有些列需要先被处理。 */
	public String[] getFirstColumns() { ... }

	/** 有些列需要后被处理。 */
	public String[] getLastColumns() { ... }
}

=======以下是具体的字典例子=======。

/**
 * 通过使用注解来定义字段校验。
 */
public class BattlePositionEntry extends Entry {
	/** 站位1。 */
	@Min(value = 1)
	public int num1;

	/** 站位2。 */
	public int num2;
}

/**
 * 这里存放字典条目的内部数据结构并不是map,而是一个数组。
 */
public class BattlePositionDict extends Dict<BattlePositionEntry> {
	private volatile int[][] positions;
	public boolean process() { ... }
	public int[][] getPositions() { ... }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值