创建一个新的对象类或编写一个转换子类对象的方法?或者是其他东西?表现不是偏好

Jos*_*man 19 java composition

我把两个单独的程序放在一起,玩一个名为'Crazy Eights'的纸牌游戏.

我为这个程序编写的类基于一个默认的"card"包,它提供了扑克牌对象和扑克牌的一些通用方法.

我采取了两种不同的方法来实现这一点,这些方法本身都是功能性的.

这是两个UML类图,描述了两种方法:

继承子类'转换'方法

在此输入图像描述

具有类似方法的组合子类

在此输入图像描述

正如你在方法1中看到的,EightsCard类包含一个方法转换(Card)这里是方法:

  /**
   * Converts a Card into an EightsCard
   * @param card The card to be converted
   * @return The converted EightsCard
   */
   public EightsCard convert(Card card) {
     if (card != null) {
     EightsCard result = new EightsCard(card.getRank(), card.getSuit());
     return result;
     } 
     return null;
   }
 }
Run Code Online (Sandbox Code Playgroud)

此方法允许您从CardCollection调用方法,否则这些方法将不合法.例如,在EightsPlayer类的play方法中如下所示:

  /**
   * Removes and returns a legal card from the player's hand.
   */
  public EightsCard play(Eights eights, EightsCard prev) {
    EightsCard ecard = new EightsCard(0, 0);
    ecard = ecard.convert(searchForMatch(prev));
    if (ecard == null) {
      ecard = drawForMatch(eights, prev);
      return ecard;
    }
    return ecard;
  }
Run Code Online (Sandbox Code Playgroud)

方法2不需要任何转换,因为类似的方法已经在扩展CardCollection的新类EightsCardCollection中编写.现在播放方法可以这样写:

  public EightsCard play(Eights eights, EightsCard prev) {
    EightsCard card = searchForMatch(prev);
    if (card == null) {
      card = drawForMatch(eights, prev);
    }
    return card;
  }
Run Code Online (Sandbox Code Playgroud)

这让我有几个问题:

  • 除了个人偏好之外,这两种方法都有任何优势吗?
  • 有没有更好的方法来编写这个程序?

例如,它可能会更好写"相似"的类这是更具体的1,并且不使用缺省类2可言.

1 在类图中标有'crazyeights.syd.jjj'或'chaptwelvetofort'.

2在类图中标记为'defaults.syd.jjj'或cards.syd.jjj'.

Sim*_*erg 10

子类太多了

这两种方法都不是很好,因为它们都有不必要的子类.为何EightsCard延伸Card?如果你想实施其他纸牌游戏怎么办?(有很多,你知道......)你会为每个纸牌游戏制作一个子类吗?请不要.

我会有这些课程:

  • CardCollection
  • 播放机

我甚至没有一个Deck类,因为它似乎只是在CardCollection 没有提供任何更多功能的情况下进行扩展.

然后我会为每个游戏实现一个EightsController类,所以一个类处理该游戏的游戏逻辑.没有针对EightsCard的特定类,没有EightsCardCollection的特定类等.

原因很简单:除此之外你不需要任何东西.无论您正在玩哪种纸牌游戏,卡和CardCollection都完全相同.所有游戏中的玩家也是同样的东西.

  • @JoshHardman我真的建议在[codereview.se]上发表评论.如果你这样做,我保证会发表评论! (2认同)

Luc*_*oss 5

关于那些领域模型,我同意Simon Forsberg的说法太复杂了,我知道它们的目的是为了展示一些概念,但即便如此,他们也可以使用更现实的例子,比如汽车中的组件和他们的关系.您可能只需要两个域类,即Card和Player.对于有序的卡片集合,请使用List<Card>.在谈到交易,轮流等方面,如何组织游戏逻辑有很大的创造空间.通常,最好是从其他类型中组合类型,而不是在很大程度上依赖于在实践中不太灵活的继承.

在性能方面,适用通用规则.例如,尽可能重用对象.如果你总是使用52张牌,那么你就没有理由选择卡级.可能没有比在任何地方重用枚举值更好的表现了.

enum Card {
    ACE_CLUBS,
    TWO_CLUBS,
    // ...
    ACE_DIAMONDS,
    // ...
}
Run Code Online (Sandbox Code Playgroud)

(你不能真正使这个枚举更复杂,因为不同的游戏使用不同的顺序,根据上下文在不同的卡上放置不同的值等)

对于性能编程的优秀实用指南,我推荐" Java性能:权威指南"一书.

  • 我更喜欢有两个枚举 - 一个用于套装,一个用于Rank - 而不是一个用于整张卡的枚举. (4认同)