[英]Java Object-Oriented Design
我想到了我的第一个 Java 项目(面向 OO)的想法。 这个项目是某种非常基本的角色扮演游戏(没有 GUI,它非常基本),所以我有一些 OOD 问题。
一个玩家(至少目前没有打算玩玩家职业)可以选择一个角色职业(你知道,战士、巫师等等……在未来他可能可以选择几个角色,这样他就可以开派对了)。 创建角色后,他可以与其他敌人作战(由程序控制)。
每个字符都有一些方法,例如:
攻击(使用武器,如果他是施法者,那么施法也可以使用攻击)。
某些角色类(如巫师)可以施展法术。 大多数法术都是攻击性或防御性的,因此它们可以使用攻击或防御方法。 例如,假设 castFireball 可以调用 Attack(20) 。 有些法术可以做其他事情,比如 castHeal 治疗角色并改变当前的生命值。
购买(未来可选)。 当然,所有字符的实现都是相同的。
建议实现:我考虑创建一个抽象类(包含诸如等级、护甲类、能力(如力量、灵巧、智慧等)之类的信息)和一些方法,如攻击和防御。其他特定类将扩展 Character,因此它看起来像:
Character (abstract)
Character Class (like fighter)
Level
Hit Points
Current Hit Points
Armor Class
.
.
.
Inventory (List)
Strength
Dexterity
Wisdom
Fighter Wizard Rouge Cleric (All extends Character)
问题:
请记住,它应该是基本的,但应该为将来的更改和添加进行计划。 它看起来像:
你想怎么进攻?
3
你想施展哪个咒语?
1
你用火球击中敌人,并造成 20 点伤害。
这很模糊,但你明白了..
非常感谢 !!
一般来说,只有当它们之间存在 is -a关系时,类B
应该是A
的子类 - 也就是说,如果说B
任何实例也是A
的实例是有意义A
。 通过应用这一点,您可以看到,例如,字符类是Character
子类的唯一可行候选者:A Warrior
是Character
,但不是Weapon
是Character
。 相反,其他类和Character
之间存在has-a关系:一个Character
有一个Weapon
。 在这种情况下,您应该使用组合: Character
类可以有一个Weapon
类型的字段(或者,更有可能是一个List<Weapon>
类型的字段,以便您可以拥有多个武器)。
但即使您可以创建类层次结构,也不确定您是否应该。 如果角色类之间的差异可以完全实现为统计数据的差异(大概只是类中的字段)或一些简单的能力差异,那么您可能只需要Character
类。 另一方面,如果行为差异很大并且您最终会得到一堆if
语句来为不同情况下的各种字符类选择适当的行为,那么引入子类可能是明智的。 但是,作为@plalx 和@B。 Dalton 指出,通常可以使用组合来代替,将行为差异提取到抽象的CharacterAbilities
类及其子类。
我建议不要让Character
成为(例如) Fighter
的抽象基类。 成为一名战士只是角色的一个属性。 我只是告诉你,例如,他可以挥舞剑和穿板甲。 在某些游戏中,假设Warrior
角色将始终是战士。 然后,当需求发生变化时,角色可以将职业更改为法师,这将是一个完整的数据迁移问题,而不是简单的属性更改。 钾
让你的继承树尽可能地浅。 尽可能使用聚合和组合而不是继承。
在这里使用抽象类效果很好,因为所有其他字符类都将从这个类扩展而来,并且类本身永远不会被实例化。
这是一个偏好问题,如果您的能力比整数更复杂,您可以考虑将它们作为一个类,但是如果您所做的只是添加临时增益/减益,我建议为每个能力设置两个整数:一个用于当前的能力值另一个是没有增益/减益的基础值。
将库存作为一个类是一个好主意。 有些人可能会想创建一系列库存物品并根据游戏需要对其进行操作。 我认为创建一个单独的类可以很好地封装所有内容,即使您只是在操作数组。
枚举在创建武器时很有用,但我也建议为此创建一个单独的类。 如果您对所有项目使用枚举,您最终可能不得不使用大量数学,特别是除法和模块化来获取项目类型。 创建一个项目类并将其扩展到不同的项目类型允许所有项目使用父类类型包含在一个公共数组中,同时为它们提供不同的统计/能力/用途。
法术可以遵循类似于我上面描述的物品的方式(实际上,如果您想将它们保存在库存中,则法术可以是物品)。 确保有一些枚举来描述法术及其功能,然后在施法时有一种解释这些的方法。
类应该有一个单一的职责(或者更具体的一个改变的原因)
1)抽象类看起来要走的路,因为你可以在类中包含共同的行为,减少重复。 接口仅定义“合同”
2)见开场白,听起来像是另一种责任。
3) 见 2
4)取决于内容,课程可能会更好
5)也许是一个不同的抽象类继承字符以确定拼写属性。 避免静态方法。 也值得一看咒语的设计模式。 可以有一个带有“castSpell”方法的接口,每个咒语都实现自己的功能。
有很多不同的选择 - 最好去看看什么有效。 如果卡住了,贴上代码。
至于武器、盾牌和法术,我会将它们建模成两个界面:
applyEffect()
方法(可能创建一个基本能力的副本,然后在那些上运行所有被动物品的applyEffect()
以获得带有物品的最终能力)performAction(Character self, Character target)
以某种方式修改拖曳HealSpell
角色,例如HealSpell
实现将增加角色的生命值统计, Dagger
将对目标执行攻击。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.