背景
我目前正在开发一款游戏,其中将有几种类型的家具,如椅子,桌子或绘画供玩家互动。为此我创建了一个抽象类GameObject
,它处理所有这些对象的共同点(例如绘图,保持位置变量等)。家具件将有一些不同的参数,例如宽度和高度(整数),以及当用户选择与之交互时会发生什么(例如:椅子 - >如果玩家靠近,坐下,桌子 - >什么都没有,绘画 - >独立于距离来检查。可以从菜单创建家具,返回所选片段的某种标识符(当前为整数)。
问题:
我该如何实施不同的家具?
一种方法是为每件家具创建一个子类。但这有两个缺点;首先,很难管理那么多的类,其次,当创建家具时,GameObject的正确子类将以某种方式基于标识符创建(参见后续问题)。
对我来说,最合乎逻辑的选择似乎是创建一个通用类,它接受构造函数中的width和height参数以及可在用户单击对象时运行的runnable / other接口。不同的值可能存储在数据库中并根据标识符进行检索,但问题仍然出现在不同的操作中,因为Runnables无法存储在外部,这导致了与解决方案1相同的问题;许多不同的类,其中必须为当前对象选择一个。
后续问题: 根据家具和动作的类型,似乎可能需要使用其他方法的更高级的子类。如果是这样的话,无论前一个问题的解决方案如何,根据标识符选择实现哪一个的问题仍然存在。我不想使用巨大的switch语句来实例化不同的类,所以有什么方法可以解决这个问题吗?
该游戏适用于Android平台,但可能会有未来的IOS端口,因此特定于Java的答案不是优选的,但可以接受。
答案 0 :(得分:2)
忘记泛型类;您应该创建子类,如您在第一个选项中所示。关于你的缺点:
很难管理那么多的课程
为什么呢?如果您创建子类,您将执行以下操作:
GameObject chair = new Chair();
如果你遵循通用模式,你会做这样的事情:
GameObject chair = new GameObject(Type.CHAIR);
创建两者的努力几乎相同,但使用第一个产品可以获得更多好处。不同之处在于,如果不进行大量条件验证,则无法使用第二种方法处理不同的操作。此外,您的核心将与您现有的对象高度耦合,这意味着如果您更改其中一个类,则需要更改核心,反之亦然。使用第一个选项,您可以执行以下操作:
selectedObject.makeAction();
它将根据它保留的实例调用正确的操作。如果您遵循通用方法,它将如下所示:
if(selectedObject.getType() == Type.CHAIR) {
//do char action. Notice that this ins't even a method provided by GameObject, you will need to get this from another place, since the GameObject is generic.
} if(selectedObject.getType() == Type.TABLE) {
//do table action
} if....
创建家具时,GameObject的正确子类将以某种方式基于标识符
创建
我没有理解你的观点。您不需要基于id创建,您只需要创建适当的类。在创建obejcts时,您已经知道对象类型,您只需要实例化正确的类。
答案 1 :(得分:1)
我肯定会选择不同类型家具的子类。
而不是返回标识符的菜单,您可能会在菜单上想到返回您需要实例化的类名(我想在显示菜单时您知道哪个类将代表每个条目)。这样就可以避免出现描述的标识符问题。
关于可以对每个部分执行的操作,您可以使用接口:
每个家具类将根据他们的可行动作实现一组界面:
Interface IExaminable {
public <result> examine();
}
Interface IBuyable {
public <result> buy();
}
然后您可以使用isntanceof运算符(如果需要)轻松检查对象是否可以检查。
希望有所帮助
答案 2 :(得分:1)
在不考虑所有if和but的情况下,很难为这个问题找到一个完美的设计解决方案。
但是,游戏的一个关键部分是项目(家具,绘画等)与可以对每个项目执行的操作之间的关系。这就是你如何建模这种关系(使用组合):
动作:表示游戏动作的界面。包含一个名为performAction的方法。
SittingAction:实现Action的具体类。代表坐着的游戏动作。实现performAction方法以定义执行坐标操作的代码。
ExamineAction:实现Action的具体类。表示用于检查项目的游戏操作。实现performAction方法以定义用于执行检查操作的代码。
同样,您可以为游戏中可执行的每种操作定义一个操作。
GameItem:表示游戏中项目的类。包含所有项目共有的属性,例如项目名称,宽度,宽度,深度等,以及这些属性的getter和setter。 GameItem'具有Action类型的实例变量'和一个构造函数,它使用Action参数初始化Action。 GameItem还定义了一个名为onInteraction的方法,您可以在用户与GameItem交互时调用该方法。此方法将通过调用Action实例变量上的performAction方法来委派执行与GameItem关联的Action的任务。因此,任何实例化GameItem的类都必须将相应的Action传递给GameItem构造函数,该构造函数表示与GameItem关联的Action。当用户与项目交互时,只需调用onIneraction方法即可。
GameController:一个侦听用户事件并调用与之交互的GameItem上的onIneraction方法的类。
就是这样。干净简单。不需要任何if else语句来检查要对哪个项执行什么操作。 Simpy使用适当的Action实例实例化所有GameItem实例,并让您的GameController监听用户输入,调用与之交互的GameItem上的onIneraction方法。