库存项目使用的设计模式建议

时间:2015-11-16 09:38:10

标签: java oop design-patterns adventure

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

我正在应用MVC架构,我正在通过从ItemFactory类中的Tiled地图文件中读取来创建Items。它们似乎适合这种游戏。

游戏中有多个项目影响游戏,特别是角色。 (在这种情况下,角色与玩家相同)

有一个角色模型,它有一个内部类库存,它基本上由一个项目的ArrayList组成。

字符控制器有一个名为takeItem的函数,它接受一个容器参数(即shelf),它还有一个项目的ArrayList,然后删除内部的内容并放入库存。

它有一个名为useItem的函数,接受一个int索引并使用相应索引中的项。

在那之前,一切都很好。

现在主要问题是,这些项目有特定用途。例如,健康药水可以增加角色的健康,隐形药水可以使角色看不见等。

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

到目前为止,我认为这样的事情: 1-我没有向项目类添加任何功能。它只有名称,描述和Enumerated ItemType和int power 2-我正在角色控制器的useItem()方法中做所有工作,即

if (itemBeingUsed.getType() == Common.ItemType.POTION)
    `characterModel.increaseHealth(itemBeingUsed.getPower())`

正如你所看到的,这看起来很奇怪,因为角色控制器就像一个项目解释器。

3-另一种方法可能是创建一个带有角色控制器的ItemInterpreter类。虽然这看起来更优雅,但它会让我在角色控制器中做一堆不必要的函数,比如“increaseCharacterHealth”函数,它会调用字符模型的increaseHelth()函数等等。

另一个可能的问题是我使用角色控制器的功能来使用物品,但物品也可能影响游戏,即减慢时间,但角色控制器低于游戏的类层次结构,不能访问游戏/游戏控制器功能。至少现在看起来比较慢,所以看起来我可以在CharacterController类中使用Items但我想知道你的意见,如果它是一个好的设计或什么可能更好。

清除问题的一些代码:(注意:它们不完整) 注意:我将诸如ItemType,Direction等的枚举类型放在Common类中,这对所有类都是通用的。

在CharacterController中使用item函数:

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");
    }

我没有提供所有代码,但如果我不清楚解释那么我可以。

2 个答案:

答案 0 :(得分:4)

这是接口,继承和多态发挥作用的经典案例。每当你使用switchif序列时,你应该考虑多态性。

在这种情况下,为可用项定义接口或抽象类。

public interface Useable {
   public void useItem(Person personUsing);
}

现在每个项目只是实现可用,您可以检查一个项目是否可用,如果它显示使用它的选项并在使用时调用该方法。

答案 1 :(得分:1)

作为一个SOA(面向服务的体系结构)开发人员,我不会在我的项目中添加逻辑,因为在这种情况下我的代码很难分解和合理化。此外,如果您想要可扩展的代码,请记住composition is far better than inheritance

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); 
}

我会定义一些处理逻辑的项效果:

AbstractItemEffect

我使用所有对象的接口在我的类之间创建低耦合(这提供了更具可伸缩性,可维护性和可测试性的代码)。

如果要定义默认行为,可以定义抽象类[ { "item": "health potion", "effect": "heal", "parameters": { "hp": 100 } }, { "item": "mana potion", "effect": "regen", "parameters": { "mp": 150 } }, { "item": "mana potion", "effect": "drunk", "parameters": { "duration": 1000 } }, ... [ "什么都不做"在所有方法的扩展项目效果中,只需为每个效果定义活动方法。

然后,如果您想要一个动态可配置游戏,您可以在文件/数据库中定义项目和效果的交互。这是一个JSON示例:

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.

使用此架构,您可以将效果附加到许多项目,将项目附加到多种效果。这可以防止您进行代码重复。

同时,每个项目和项目效果将处理其自身的复杂性,并且不会使整个系统更复杂。对于模式'开关盒而言,情况并非如此。就像你在fun( object.getA() != null ? object.getA() : object.getB() != null ? object.getB() : object.getC() != null ? object.getC() : object.getD() != null ? object.getD() : object.getE() != null ? object.getE() : "error" ) 中描述的一样。想想你的课程,如果你有100个效果和200个项目......

抱歉我的JAVA代码不好/不完整!