【问题标题】:How to avoid instanceof from this kind of case?如何避免这种情况下的instanceof?
【发布时间】:2020-07-21 07:40:07
【问题描述】:

我当前在 Player.java 中的代码是这样的:

    public boolean canPutCard(Card card) {
        if (!handCards.contains(card)) {
            return false;
        }
        if (card instanceof ActivableCard) {
            boolean hasEmpty = false;
            int i = card instanceof CharacterCard ? 0 : 1;
            for (int j = 0; j < fieldCards[i].length; ++j) {
                if (fieldCards[i][j] == null) {
                    hasEmpty = true;
                }
            }
            if (!hasEmpty) {
                return false;
            }
        }
        return (card instanceof LandCard && !hasPutLandCard) || (card instanceof PoweredCard
                && ((PoweredCard) card).getPowerNeeded() <= currentElementValue[card.getElementType().ordinal()]);
    }

我想避免在这里使用多个 instanceof,因为他们称之为“代码气味”,而是使用多态性。所以我能做的就是把它改写成这样:

    public boolean canPutCard(LandCard card) {
        return !hasPutLandCard;
    }

    public boolean canPutCard(PoweredCard card) {
        return card.getPowerNeeded() <= currentElementValue[card.getElementType().ordinal()];
    }

    private boolean canPutCard(int i, PutableCard card) {
        boolean hasEmpty = false;
        for (int j = 0; j < fieldCards[i].length; ++j) {
            if (fieldCards[i][j] == null) {
                hasEmpty = true;
            }
        }
        return hasEmpty;
    }

    public boolean canPutCard(PutableCard card) {
        return canPutCard(1, card);
    }

    public boolean canPutCard(CharacterCard card) {
        return canPutCard(0, card);
    }

    public boolean canPutCard(Card card) {
        return handCards.contains(card);
    }

类:

abstract class SkillCard extends Card implements PoweredCard
class CharacterCard extends Card implements PoweredCard, PutableCard
class LandCard extends Card

但是,它肯定不会起作用,因为它不会检查所有情况..

在这种情况下是否可以避免使用instanceof而使用多态性?

【问题讨论】:

  • 您可以使 canPutCard 方法成为通用方法,但是您的 fieldsCards 至少有 2 个维度,并且维度取决于不同类型的卡片,我看到一个用于 CharacterCard,另一个用于 PutableCard,所以您必须使用instanceof 来确定您要查找的维度,另一方面,您有LandCard 类型的PutLandCard 布尔属性,这也意味着instanceof。
  • 我不明白通用方法如何解决这个问题...
  • “我想避免在这里使用多个 instanceof,因为他们称之为“代码气味”” ...所有活着看到这样代码的人也是如此,但是这不是他们可以决定的。您所要做的就是如何处理提供给您的代码。

标签: java oop design-patterns polymorphism


【解决方案1】:

Instanceof 操作符通常可以替换为适当依赖 java 虚拟调度。将决策逻辑移至 Card 类,如下所示

public abstract boolean canPutCard(Player player);

然后在 Card 子类中实现适当的逻辑,例如:

class LandCard extends Card {
    @Override public boolean canPutCard(Player player) {
         return !player.hasPutLandCard() && player.handContains(this);
    }
}

class CharacterCard extends Card implements PoweredCard, PutableCard {
    @Override public boolean canPutCard(Player player) {
         return !player.hasEmptyCharacterCardField() && player.handContains(this);
    }
}

... 等等。播放器类将需要具有所需的查询方法。

【讨论】:

  • "Instanceof 操作符通常可以通过适当依赖 java 虚拟调度来代替。" ...确实如此。但是,这假设您可以控制层次结构并且能够修改代码库。如果没有,那么......好吧...... instanceof 让你通过。
  • 这可以解决,但是如果Card 接收Player 作为参数,而Player 本身有Cards,是不是紧耦合,不是不好的设计吗?
  • @nafkhanzam 你可以创建一个接口,卡作为参数而不是具体类接收,如果与 Player 的紧密耦合是一个问题,你在这里的耦合已经比以前少了,因为 Player 不依赖于卡层次结构细节
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多