我正在开发卡片游戏UNO的实现(主要用于运行模拟测试一些房屋规则,但这是一个不同的故事)。
对于那些从未玩过它的人来说,它与Crazy Eights相似。玩家轮流在弃牌堆上打牌。该卡必须匹配数量或颜色。还有抽奖卡,迫使下一位玩家抽取两张或四张牌。它的规则也非常友好,这非常有趣。
我有一张Card
课程,其中包含该卡的value
和color
。我想要做的是创建扩展DrawCard
的{{1}}。然后,在确定游戏机制时,我会使用Card
来测试我是否有instanceof
。
我知道DrawCard
经常有问题,但这对我来说似乎没问题。通常这些卡片的处理方式相同,只有少数特殊卡片的处理方式不同,并且只能在特定于卡片类型的特殊情况下使用(虽然这看起来像滑坡但是......)
我可以在instanceof
课程中使用标记(实际上,每种类型的卡片都有自己的'值'),但我仍在扩展Card
以便有一些其他类型的卡可能有的方法(它不仅仅是一种识别手段)。使用Card
对我来说似乎更为通用,因为我不需要知道instanceof
的哪些值需要这种特殊行为,例如,添加Draw 8会很容易卡片显示Draw 2和Draw 4的当前内容。(说这让我想知道我是否可以使用某种嵌套枚举或其他东西,但我不知道)
我知道两种解决方案都能正常运行(让程序运行)。使用value
对我来说感觉更好,但我没有经验可以理解它是否合适。这是一个糟糕的设计吗?
答案 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的评论进行编辑:
在播放卡片后处理操作时,您可以利用接口覆盖处理操作的功能。由于这是上下文,我可能会推荐三种不同的接口:
IDrawCard
ICommonCard
ICard
其中IDrawCard
是您需要的通用接口,它可能处理一些通用方法,而另外两个接口处理这两种特定类型的需求。
然后说你有一个名为ICommonCard
的动作处理程序方法,可以这样定义:
handleAction
然后当你调用那个函数时,你可以将一个接口类型的对象传递给重载函数(一个选项是每个类型都有一个成员变量,如果它要去成为一个或另一个,将不是void handleAction(ICard card)
{
// do ICard stuff here
return;
}
void handleAction(IDrawCard card)
{
// do IDrawCard stuff here
return;
}
的那个传递给函数。)