经常使用实例是好的做法吗?

2022-09-03 09:42:53

方案。我正在编写与游戏相关的代码。在该游戏中,a(它也是一个类)有一个列表。还有其他类型的项可继承自 ,例如 或 。PlayerItemItemContainerItemDurableItemWeaponItem

显然,对我来说,拥有它非常方便。但是当我获得玩家物品时,我区分物品类型的唯一方法是使用关键字。我敢肯定我已经读过,对它进行评论是一种不好的做法。List<Item>instanceof

在这种情况下可以使用它吗?还是我应该重新考虑我的所有结构?


答案 1

假设我正在编写一些库存代码:

public void showInventory(List<Item> items) {
    for (Item item : items) {
        if (item instanceof ContainerItem) {
            // container display logic here
        }
        else if (item instanceof WeaponItem) {
            // weapon display logic here
        }
        // etc etc
    }
}

这将编译并正常工作。但它错过了面向对象设计的一个关键思想:你可以定义父类来做一般有用的事情,并让子类填写特定的、重要的细节。

上述替代方法:

abstract class Item {
    // insert methods that act exactly the same for all items here

    // now define one that subclasses must fill in themselves
    public abstract void show()
}
class ContainerItem extends Item {
    @Override public void show() {
        // container display logic here instead
    }
}
class WeaponItem extends Item {
    @Override public void show() {
        // weapon display logic here instead
    }
}

现在,我们有一个地方可以查看,即方法,用于清单显示逻辑的所有子类。我们如何访问它?容易!show()

public void showInventory(List<Item> items) {
    for (Item item : items) {
        item.show();
    }
}

我们将所有特定于项目的逻辑保留在特定的 Item 子类中。这使您的代码库更易于维护和扩展。它减少了第一个代码示例中长 for-each 循环的认知压力。而且它准备在你甚至还没有设计的地方重复使用。show()


答案 2

恕我直言,使用的是一种代码气味。简单地说 - 它使你的代码成为过程性的,而不是面向对象的。执行此操作的 OO 方法是使用访问者模式instanceof

enter image description here

访问者模式还允许您轻松地在其上构建 s 和它,从而实现关注点分离,从而缩短、更清晰、更易于阅读和测试代码。decoratorchain of responsibility

另外,你真的需要知道确切的类吗?你不能利用多态性吗?毕竟是一个公正的。AxeWeaponSword