Java 库存中物品使用的设计模式建议

Java 库存中物品使用的设计模式建议,java,oop,design-patterns,adventure,Java,Oop,Design Patterns,Adventure,不幸的是,由于我学校的面向对象软件工程项目,我正在用java和slick2d制作一个冒险游戏 我正在应用MVC体系结构,通过读取ItemFactory类中的平铺映射文件来创建项目。他们似乎适合这种游戏 游戏中有多个项目会影响游戏,尤其是角色。(角色在此上下文中与玩家相同) 有一个字符模型,它有一个内部类库存,基本上由一个项目数组列表组成 角色控制器有一个名为takeItem的函数,该函数接受一个容器参数(即shelf),该容器参数也有一个项目的ArrayList,然后删除其中的内容并放入清单 它

不幸的是,由于我学校的面向对象软件工程项目,我正在用java和slick2d制作一个冒险游戏

我正在应用MVC体系结构,通过读取ItemFactory类中的平铺映射文件来创建项目。他们似乎适合这种游戏

游戏中有多个项目会影响游戏,尤其是角色。(角色在此上下文中与玩家相同)

有一个字符模型,它有一个内部类库存,基本上由一个项目数组列表组成

角色控制器有一个名为takeItem的函数,该函数接受一个容器参数(即shelf),该容器参数也有一个项目的ArrayList,然后删除其中的内容并放入清单

它有一个名为useItem的函数,获取一个int索引,并在适当的索引中使用该项

在那之前,一切都很好

现在主要的问题是,这些物品有特定的用途。例如,健康药水增加人物的健康,隐形药水使其隐形等等

为了维持一个好的设计,我如何以及在哪里可以解释和附加这些项目的功能

到目前为止,我认为是这样的: 1-我没有向item类添加任何函数。它只有名称、描述和枚举ItemType以及整数幂 2-我正在做角色控制器的useItem()方法中的所有工作,即

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, ...
    }
}
使用此体系结构,可以将一个效果附加到多个项目,将一个项目附加到多个效果。这样可以防止代码重复