Java 库存中物品使用的设计模式建议
不幸的是,由于我学校的面向对象软件工程项目,我正在用java和slick2d制作一个冒险游戏 我正在应用MVC体系结构,通过读取ItemFactory类中的平铺映射文件来创建项目。他们似乎适合这种游戏 游戏中有多个项目会影响游戏,尤其是角色。(角色在此上下文中与玩家相同) 有一个字符模型,它有一个内部类库存,基本上由一个项目数组列表组成 角色控制器有一个名为takeItem的函数,该函数接受一个容器参数(即shelf),该容器参数也有一个项目的ArrayList,然后删除其中的内容并放入清单 它有一个名为useItem的函数,获取一个int索引,并在适当的索引中使用该项 在那之前,一切都很好 现在主要的问题是,这些物品有特定的用途。例如,健康药水增加人物的健康,隐形药水使其隐形等等 为了维持一个好的设计,我如何以及在哪里可以解释和附加这些项目的功能 到目前为止,我认为是这样的: 1-我没有向item类添加任何函数。它只有名称、描述和枚举ItemType以及整数幂 2-我正在做角色控制器的useItem()方法中的所有工作,即Java 库存中物品使用的设计模式建议,java,oop,design-patterns,adventure,Java,Oop,Design Patterns,Adventure,不幸的是,由于我学校的面向对象软件工程项目,我正在用java和slick2d制作一个冒险游戏 我正在应用MVC体系结构,通过读取ItemFactory类中的平铺映射文件来创建项目。他们似乎适合这种游戏 游戏中有多个项目会影响游戏,尤其是角色。(角色在此上下文中与玩家相同) 有一个字符模型,它有一个内部类库存,基本上由一个项目数组列表组成 角色控制器有一个名为takeItem的函数,该函数接受一个容器参数(即shelf),该容器参数也有一个项目的ArrayList,然后删除其中的内容并放入清单 它
if (itemBeingUsed.getType() == Common.ItemType.POTION)
`characterModel.increaseHealth(itemBeingUsed.getPower())`
正如您所看到的,这看起来很奇怪,因为角色控制器的行为就像一个项目解释器
3-另一种方法可能是创建一个接受字符控制器的ItemExplorer类。虽然这看起来更优雅,但它会让我在角色控制器中执行一些不必要的函数,比如“increaseCharacterHealth”函数,它调用角色模型的increaseHelth()函数等等
另一个可能的问题是,我正在使用角色控制器的功能来使用项目,但项目也可能会影响游戏,即减慢时间,但角色控制器位于游戏的类层次结构之下,无法访问游戏/游戏控制器功能。减缓游戏时间等似乎不是这样,至少现在是这样,所以看起来我可以使用CharacterController类中的项目,但我想知道你的意见,如果这是一个好的设计或什么可以更好
清除问题的一些代码:(注:它们不完整)
注意:我将枚举类型(如ItemType、Direction等)放在一个公共类中,该类对所有类都是公共的
在CharacterController中使用项函数:
public void useItem(int index){
Item item = ((Character)obj).inventory.takeItem(index);
if (item != null) {
if (item.getType() == Common.ItemType.POTION) {
((Character)obj).increaseHealth(item.getPower()); // I have extended a Person class, now I have to typecast to character everytime, which is also nonsense
}
else
System.out.println("and other items..");
}
else
System.out.println("Cannot use");
}
我没有把所有的代码都放进去,但是如果我解释不清楚的话,我可以。这是一个典型的例子,接口、继承和多态性在其中发挥作用。每当使用<代码>开关<代码>或<代码> > <<代码>时,应考虑多态性。 在本例中,为可用项定义接口或抽象类
public interface Useable {
public void useItem(Person personUsing);
}
现在,每个项都只实现了useable,您只需检查一个项是否可用,如果可用,则显示使用它的选项,并在使用时调用该方法。这是一个典型的情况,其中接口、继承和多态性发挥了作用。每当使用<代码>开关<代码>或<代码> > <<代码>时,应考虑多态性。 在本例中,为可用项定义接口或抽象类
public interface Useable {
public void useItem(Person personUsing);
}
现在,每个项都实现了useable,您只需检查一个项是否可用,是否可用,显示使用它的选项并在使用时调用方法。作为一名SOA(面向服务的体系结构)开发人员,我不会向我的项添加逻辑,因为在这种情况下,我的代码很难分解和合理化。此外,请记住,如果您想要可伸缩的代码
public interface ItemInterface {
public String getName();
public String[] getCharacteristics();
}
我将定义一些处理逻辑的项目效果:
public interface ItemEffectInterface {
public String getName();
public void affectCharacter(ItemInterface item, CharacterInterface character, parameters);
public void affectInventory(ItemInterface item, InventoryInterface inventory, parameters);
public void affectGame(ItemInterface item, GameInterface game, parameters);
}
我为所有对象使用接口来创建类之间的低耦合(这提供了更具可伸缩性、可维护性和可测试性的代码)
如果您想在extender item effects中为所有方法定义默认行为“不做任何事情”,并且只为每个效果定义活动方法,那么您可以定义一个抽象类AbstractItemEffect
然后,如果您想要一个动态可配置的游戏,您可以在文件/数据库中定义项目和效果的交互。下面是一个JSON示例:
[
{
"item": "health potion",
"effect": "heal",
"parameters": {
"hp": 100
}
},
{
"item": "mana potion",
"effect": "regen",
"parameters": {
"mp": 150
}
},
{
"item": "mana potion",
"effect": "drunk",
"parameters": {
"duration": 1000
}
},
...
[
然后使用服务类将效果映射到使用时的项目:
public class ItemUser {
private Map itemEffects = new HashMap();
// Call it at service initialization after interpreting the configuration
// (configuration is optional, you can call it directly of course).
public void addItemEffect(ItemInterface item, ItemEffectInterface itemEffect, parameters) {
Map effect = new HashMap();
effect.push("effect", itemEffect);
effect.pust("parameters", parameters);
this.itemEffects.put(item.getName(), effect);
}
// Call it when you want to use an item.
public void useItem(ItemInterface item, Character character, GameInterface game, InventoryInterface inventory) {
Map itemEffects = this.itemEffect[item.getName()];
// Process all the effects attached to your item
// on game, character, inventory, ...
}
}
使用此体系结构,可以将一个效果附加到多个项目,将一个项目附加到多个效果。这样可以防止代码重复
同时,每个项目和项目效果将处理其自身的复杂性,不会使整个系统更加复杂。这与您在2.
中描述的模式“开关盒”不同。想象一下你的班级,如果你有100个特效和200个物品
对不起,我的JAVA代码不好/不完整 作为一名SOA(面向服务的体系结构)开发人员,我不会在我的项目中添加逻辑,因为在这种情况下,我的代码很难分解和合理化。此外,请记住,如果您想要可伸缩的代码
public interface ItemInterface {
public String getName();
public String[] getCharacteristics();
}
我将定义一些处理逻辑的项目效果:
public interface ItemEffectInterface {
public String getName();
public void affectCharacter(ItemInterface item, CharacterInterface character, parameters);
public void affectInventory(ItemInterface item, InventoryInterface inventory, parameters);
public void affectGame(ItemInterface item, GameInterface game, parameters);
}
我为所有对象使用接口来创建类之间的低耦合(这提供了更具可伸缩性、可维护性和可测试性的代码)
如果您想在extender item effects中为所有方法定义默认行为“不做任何事情”,并且只为每个效果定义活动方法,那么您可以定义一个抽象类AbstractItemEffect
然后,如果您想要一个动态可配置的游戏,您可以在文件/数据库中定义项目和效果的交互。下面是一个JSON示例:
[
{
"item": "health potion",
"effect": "heal",
"parameters": {
"hp": 100
}
},
{
"item": "mana potion",
"effect": "regen",
"parameters": {
"mp": 150
}
},
{
"item": "mana potion",
"effect": "drunk",
"parameters": {
"duration": 1000
}
},
...
[
然后使用服务类将效果映射到使用时的项目:
public class ItemUser {
private Map itemEffects = new HashMap();
// Call it at service initialization after interpreting the configuration
// (configuration is optional, you can call it directly of course).
public void addItemEffect(ItemInterface item, ItemEffectInterface itemEffect, parameters) {
Map effect = new HashMap();
effect.push("effect", itemEffect);
effect.pust("parameters", parameters);
this.itemEffects.put(item.getName(), effect);
}
// Call it when you want to use an item.
public void useItem(ItemInterface item, Character character, GameInterface game, InventoryInterface inventory) {
Map itemEffects = this.itemEffect[item.getName()];
// Process all the effects attached to your item
// on game, character, inventory, ...
}
}
使用此体系结构,可以将一个效果附加到多个项目,将一个项目附加到多个效果。这样可以防止代码重复
在