The pattern from the question has some implications for later maintainability. When each card is a static
, they seem more like card-types to me than actual instances of cards. This conceptual difference might not matter much when each card only exists once in the game, but will matter when you allow multiple cards of the same type.
YouWith this pattern, you can write code like if (lastCard == Card.PIG) sayOink();
. But because the ==
-operator only checks if both references point to the same object, this only works when lastCard is a reference to Card.PIG
. There might be multiple pig-cards in the game, but they are all represented by references to the one Card.PIG
object. That means if Card.PIG
has any internal state, that state will be shared by all pig-cards in the game.
When youyour game doesn't have state for individual cards, that's fine.
But if you have some mechanics where cards have a state (like counters on cards, a "tapping" mechanic like in some trading card games, etc...) or when you want cards themselves to be aware of their current location in the game (in the deck, in a player's hand, on the table), this is not going to work. You will then need somean instantiated object for each card.
for (int i = 0; i < NUM_DOG_CARDS_PER_DECK; i++) {
deck.add(new DogCard());
}
for (i = 0; i < NUM_PIG_CARDS_PER_DECK; i++) {
deck.add(new PigCard());
}
for (i = 0; i < NUM_SHEEP_CARDS_PER_DECK; i++) {
deck.add(new SheepCard());
}
The differences between different card types (like their names and images) would then be implemented in the various CardDogCard
sub-classes, SheepCard
etc.. This architecture would be most appropriate if your card types don't just differ by the values of their variables, but also have some mechanical differences which require card-specific code. That couldcode would then belong into those sub-classes.