这是instanceof的可接受用途吗?

时间:2014-07-12 04:10:53

标签: java oop instanceof

我正在开发卡片游戏UNO的实现(主要用于运行模拟测试一些房屋规则,但这是一个不同的故事)。

对于那些从未玩过它的人来说,它与Crazy Eights相似。玩家轮流在弃牌堆上打牌。该卡必须匹配数量或颜色。还有抽奖卡,迫使下一位玩家抽取两张或四张牌。它的规则也非常友好,这非常有趣。

我有一张Card课程,其中包含该卡的valuecolor。我想要做的是创建扩展DrawCard的{​​{1}}。然后,在确定游戏机制时,我会使用Card来测试我是否有instanceof

我知道DrawCard经常有问题,但这对我来说似乎没问题。通常这些卡片的处理方式相同,只有少数特殊卡片的处理方式不同,并且只能在特定于卡片类型的特殊情况下使用(虽然这看起来像滑坡但是......)

我可以在instanceof课程中使用标记(实际上,每种类型的卡片都有自己的'值'),但我仍在扩展Card以便有一些其他类型的卡可能有的方法(它不仅仅是一种识别手段)。使用Card对我来说似乎更为通用,因为我不需要知道instanceof的哪些值需要这种特殊行为,例如,添加Draw 8会很容易卡片显示Draw 2和Draw 4的当前内容。(说这让我想知道我是否可以使用某种嵌套枚举或其他东西,但我不知道)

我知道两种解决方案都能正常运行(让程序运行)。使用value对我来说感觉更好,但我没有经验可以理解它是否合适。这是一个糟糕的设计吗?

2 个答案:

答案 0 :(得分:1)

简短回答:不太可接受,所以是 - 这是设计缺陷的表现。 instanceof几乎总是一种气味,除非在极少数情况下,图书馆试图提供某种形式的辅助或其他丑陋的帮助,但有助于克服语言/环境的缺点。

根据这种观点,这个问题有点重复。请参阅答案:

When is it acceptable to use instanceof?

建议使用访客模式。如果您在系统中真正拥有两种不同类型,则可能是这样。

您也不必“明确”使用访问者模式,而是将其合并到您的程序流程中。所以考虑一下接口卡:

interface Card {
  void pick(Player player);
}

class DrawCard implements Card {
  void pick(Player player) {
    player.draw(value); // assume value passed in e.g. ctor
  }
}

答案 1 :(得分:0)

我会说,一般情况下,尽可能避免使用instanceof

虽然由于您没有发布任何实际代码,但它有些模糊,但在这种情况下,一种选择是实现两个不同的接口,比如{{1} }和ICard并让IDrawCard类实现Card接口,ICard类实现接口

然后,您可以通过函数签名等中的接口来区分DrawCard类(也就是说,将其称为类型的对象 DrawCard)。

根据OP的评论进行编辑:

在播放卡片后处理操作时,您可以利用接口覆盖处理操作的功能。由于这是上下文,我可能会推荐三种不同的接口:

  1. IDrawCard
  2. ICommonCard
  3. ICard
  4. 其中IDrawCard是您需要的通用接口,它可能处理一些通用方法,而另外两个接口处理这两种特定类型的需求。

    然后说你有一个名为ICommonCard的动作处理程序方法,可以这样定义:

    handleAction

    然后当你调用那个函数时,你可以将一个接口类型的对象传递给重载函数(一个选项是每个类型都有一个成员变量,如果它要去成为一个或另一个,将不是void handleAction(ICard card) { // do ICard stuff here return; } void handleAction(IDrawCard card) { // do IDrawCard stuff here return; } 的那个传递给函数。)