【问题标题】:Avoiding instanceof Java避免使用 Java 实例
【发布时间】:2015-06-20 11:45:38
【问题描述】:

我正在尝试找到一种绕过使用 instanceof 的方法。我创建了一个类 Item,它有多个子类,如 WeaponItem 和 BodyItem。现在我想做一个调用,比如equip(Item),它应该自己确定应该调用哪个重载函数,比如equip(BodyItem)。

在这种情况下,有没有办法绕过对 instanceof 的使用?您有什么建议?我听说在大多数情况下使用 instanceof 是不好的做法,因此我想知道替代方案是什么。

代码:

inv.equip(it); // inv = inventory object, it = Item

库存类中装备功能的示例我希望它如何

public void equip(HelmItem it) 
{
    if (it != this.getHelm())
    {
        this.setHelm(it);
    }
}

我以前是怎么做到的:

public void equip(Item it)
{
    if (it instanceof WeaponItem)
    {
        if (it != this.getWeapon())
        {
            this.setWeapon((WeaponItem) it);
        } 
    } etc for all subclasses of item
}

【问题讨论】:

标签: java instanceof


【解决方案1】:

确实,这可以通过访问者模式来解决。

但是,它不必是成熟的访问者,而是它的简化变体。您可以将库存传递给物品,让物品随心所欲地处理它:

abstract class Item {
    public abstract void equip(Inventory inv);
}

class HelmItem extends Item {
    @Override
    public void equip(Inventory inv) {
        inv.setHelm(this);
    }
}

class WeaponItem extends Item {
    @Override
    public void equip(Inventory inv) {
        inv.setWeapon(this);
    }
}

然后你可以打电话:

it.equip(inv)

没有instanceof 运算符。

【讨论】:

  • 这个问题确实解决了!感谢您分享您的想法!它仍然是相当违反直觉的,因为语义上说物品装备了库存,但它可以作为一种解决方案,所以谢谢! :D
  • 是的,这可以通过保留inv.equip(it) 方法来克服,但是在实现它时你可以调用it.equip(this)。这样你就有了一个集中的地方来将物品添加到库存中,这很好,因为它遵守 DRY,你也可以在那里做其他事情,比如计算添加的物品,检查库存是否已满等。
  • 虽然我们说了类似的话,但您做得更好并提供了一个完整的示例。 +1
【解决方案2】:

为什么不把方法放在Item具体类中,它自己可以装备呢?这有点违反直觉,但它会解决你的问题。

public class SomeConcreteItem extends Item {
    public void equip(Body body) {
        // Just an example.
        body.getSections().get(0).equip(this);
    }
}

这样,具体实现知道如何装备自己,使用它的类不在乎。您可以通过Item 超类引用它,并且假设Item 超类有一个抽象方法public void equip(Body body);,那么您不需要了解具体实现,因此不需要instanceof运算符。

介绍设计模式的注意事项

您应该小心引入设计模式。人们有一个坏习惯,即直接跳到复杂的模式来解决问题,而实际上可以使用更简单且(在我看来)更优雅的东西。

【讨论】:

    猜你喜欢
    • 2011-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多