实例化其子类将取决于用户输入的对象

时间:2019-06-06 14:20:22

标签: java design-patterns

请原谅愚蠢的问题,我对Java和OOP还是很陌生,我正在尝试遵循设计模式(避免使用if,switch等),但是这样做很难。

因此,我正在为自己的“游戏”项目建立武器供应商。该供应商具有对象列表。这些对象都是武器超类的所有不同实例(例如,剑,矛,斧等)。

当用户尝试购买武器时,供应商将显示武器列表,然后用户通过输入其列表索引来选择武器列表。

我现在面临两个问题:

1)如何创建其子类将取决于用户输入的对象的实例? 2)我如何调用正确的构造函数,将购买的武器的相同参数传递给要实例化的新对象?我正在尝试以尽可能多态的方式来执行此操作,避免使用ifs和switch语句。

到目前为止,我尝试过制作一个界面(iWeapon)。然后,基于该接口,我创建了一个Factory,该Factory接收武器的类型(字符串)并返回带有相应子类的武器的新实例。

这使我可以使用接口的数据类型实例化“通用”武器。但是,我不知道这是否是实现此目标的最佳方法。另外,我也不知道如何以多态的方式用新购买的武器的相同值来初始化新实例的属性。

我尝试在所有武器子类上创建方法“ getAttributesFromOtherWeapon”,该方法接收具有相同类型的对象,并仅复制这些值。我现在面临的问题是我实例化的iWeapon类型对象没有此方法,如果我在接口上包含它,我的子类将收到错误消息,指出“类必须声明为抽象或实现抽象方法'

我的供应商代码执行以下操作:

Weapon weaponToBuy = (Weapon) weaponList.get(weaponChosenIndex);
iWeapon newWeapon = weaponFactory.getWeapon(weaponToBuy.type);
newWeapon.getAttributesFromOtherWeapon(weaponToBuy);

但是,由于newWeapon是iWeapon,因此我需要在其接口上声明getAttributesFromOtherWeapon,如下所示:

public interface iWeapon {


    void getAttributesFromOtherWeapon(iWeapon iWeapon);


}

现在,在我尝试实现此方法的每个武器子类中,我都需要传递一个iWeapon而不是相应的子类类型(Sword,Spear等)。问题在于,在我的iWeapon界面中,我没有定义与武器(或任何武器子类)相对应的所有属性,因为我知道它们将被定义为常量。

我认为可能有一个开箱即用的解决方案,由于我是Java的新手,所以我没有看到。任何帮助将不胜感激

1 个答案:

答案 0 :(得分:0)

对此有多种解决方案。

1。使用generics

interface Weapon<T extends Weapon> {
    public Weapon getAttributesFromOther(T t);
}

class Axe implements Weapon<Axe> {
    @Override
    public Weapon getAttributesFromOther(Axe other) {
        // TODO get those attributes
        return this;
    }
}

...等等

专业人士

如果将类定义为Sword#getAtributesFromOther,则

Sword仅采用implements Weapon<Sword>

缺点

如果错误地声明了类似class Dagger implements Weapon<Pitchfork>的内容,那么getAttributes将采用Pitchfork

在我看来,这可以忽略不计,因为它全是编译时的,但值得考虑。

对于未知的武器类型,您的武器参考也应在运行时更改为Weapon<?>

2。声明一个WeaponProperties类,该类扩展了一些参数化的Map,并在Weapon界面中提供了一个getter / setter对

专业人士

这将适用于所有武器,只需检查该属性是否存在。

您可以轻松地合并多种武器共有的属性。

缺点

所有武器都有很多样板,如果允许的话,从不同武器类型复制属性时,会包含许多“安全”代码。

3。可能还有 更好的东西-如果我有个主意会进行编辑

注释

  • 请确保遵循Java code conventions,例如匈牙利表示法没有什么问题,但每种类型都应始终为CamelCase(与变量名camelBack相反)。这与您的iWeapon界面有关,您可以轻松地将其重构为Weapon-请参见上面的示例。
  • 事后思考:我意识到示例中的getAttributes...方法返回Weapon,但这与这种情况无关-您可以安全地返回void