0

为了详细说明我的问题,具体情况是这样的:

如果我有一个模拟或游戏项目,例如,一个Monster具有不同统计数据作为成员数据(、等)的类,hitPointsRemaining并且AttackDamage我希望拥有任意数量的具有恒定基本统计数据(、、等)的不同类型的怪物MaxHPSpeed那么我查看需要使用此类的三种方式:

  1. 一个具有接口的实际类,用于在整个代码中使用 Monster 对象(例如,“ Monster”)
  2. 不同类型怪物的实际“数据”。(概念上可能的子类?虽然我确定这不是正确的解决方案)例如:地精、龙、独眼巨人等
  3. 当角色在游戏中遇到它们时代表不同怪物的实际实例化Monster对象(随时可能有多个相同类型的实例)

我想知道大多数设计师是如何实现这一点的。我的想法如下:

Monster-随着开发的进展,为每种类型的怪物创建一个类,然后再创建一个新的子类是没有意义的。这似乎是一个非常混乱且无法维护的解决方案,特别是如果不同怪物类型的数量有数百种差异,并且每种类型之间的差异还不足以保证一个新的子类

-相反,我的解决方案如下: 1. 有一个文件可以添加到包含所有不同Monster类型的数据及其特征的表中。该表可以在项目开发的任何时候添加。

  1. 编写一个函数以将表中的数据加载到Monster对象中。

  2. 在程序开始时编写一个初始化调用,可能在某种MonsterManager类中,以解析文件并创建实例化Monster对象的静态或成员向量,其中所有“基本”统计信息从文件中的表中填充(即,起始生命值等)

  3. 每当我想实例化Monster某种类型的新对象以添加到某人的军队或与某人会面时,Monster从向量中选择一个(随机或通过某些决定因素)创建一个新Monster对象,并将其从向量中复制出来

这作为一个解决方案有意义还是我出去吃午饭?如果这不是一个好的解决方案,还有什么更好的方法?

其他补充问题:

- 为将保存在向量中的怪物数据创建一个不同的类是否有意义?我想我可以有一个名为的类MonsterData,它可以通过上面的方法构建到一个向量中MonsterManager。我可以将MonsterData对象传递给类的构造函数Monster以实际创建Monster对象,因为许多Monster对象的特征将由它们的怪物类型(MaxHP、速度等)决定,而其他东西会有所不同(CurrentHP、任何随机变量, ETC)

- 我认为这种方法是可优化的,因为你可以做一些事情,比如在表中添加一个条目,指示怪物出现在哪个级别,然后让MonsterManager初始化函数一次只加载特定级别的所有怪物以减少内存占用) - 由于我没有为此使用,存储文本字符串作为识别对象“类型”enum的手段是否有意义?Monster也许指向从 ' 向量中复制的Monster(或)的指针会更好?MonsterDataMonsterManager

我使用游戏类比是因为它在这里对我来说最有意义,但我想知道在任何情况下这种事情的最佳设计模式。

谢谢大家!

4

2 回答 2

4

继承应该用于修改/添加行为,而不是用于改变数据值。在您的示例中,似乎每个怪物都由一组属性(HP、攻击等)定义,并且您希望在游戏中实例化不同的怪物类型。你真的不需要继承。

你在MonsterData课堂上走在正确的轨道上;这就是我的处理方式(主要是我认为更有意义的类的不同名称):

// This is what you called MonsterData
// It describes how to create a monster of a specific type
public class MonsterDescription {
  private String type;   // eg. "Goblin"
  private int maxHitPoints;
  private int speed;
  ...
}

// This is an "active" instance of a monster
public class Monster {
  private int currentHitPoints;
  ...

  // static factory method
  public static Monster create(MonsterDescription desc) {
    ...
  }
}

// This is kind of what you called MonsterManager
// Contains a collection of MonsterDescription, loaded from somewhere
public class MonsterDescriptionRepository {
  // finds the description for a given type of monster
  public MonsterDescription find(String type) {
    ...
  }
}

然后是你将如何实例化一个新怪物:

MonsterDescription desc = repository.find("Goblin");
Monster monster = Monster.create(desc);
于 2012-07-14T08:37:15.970 回答
2

数据加载器方法似乎适合您的问题 - 它使其易于扩展。我建议为不同的功能创建子类 - 例如,创建一个 FlyingMonster 子类,它可以处理 Dragon 而不是 Goblin 或 Shark,这样你可以(尝试)避免拥有一个可以飞行/运行/潜水的 Monster 类;)

您的最后一个问题是关于外部数据键控 - 为此我认为指针方法是最好的:

  • 这是独一无二的
  • 它可以帮助调试
  • 您可以选择使用商店中存储的值
  • 它将显示与祖先的“is_a”连接

注意:我认为你不应该在这个阶段“关心”任何性能问题(将它们加载到内存中以减少内存占用),因为它通常会破坏设计

于 2012-07-14T08:38:51.190 回答