Page 529 - Introduction to Programming with Java: A Problem Solving Approach
P. 529
12.10 Design Practice with Card Game Example 495
see later on, if you have defined a Game class, the driver’s main method just needs to instantiate a Game ob- ject and then call playAGame and that’s it. You can’t get much more streamlined (and elegant) than that.
For each class in the Card Game program, what are its members (that is, instance variables and meth- ods)? Let’s tackle the easy classes first—Game and Card. The Game class needs three instance variables— one for the deck and two for the two hands. It needs a method for playing a game. The Card class needs two instance variables—one for a number (two through ace) and one for a suit (clubs through spades). It needs a method to display the card’s number and suit values. As a sanity check, verify that Figure 12.17’s Game and Card members match what we’ve described.
The Deck class needs an instance variable for an array of cards such that each card is a Card object. The Deck class also needs an instance variable to keep track of the current size of the deck. The Deck class needs methods for shuffling and dealing. To help with debugging, you should probably also include a method to display all the cards in the deck.
The Hand class needs instance variables for an array of cards and for a current-size value. It needs methods for displaying all the cards, adding a card to the hand, and playing a card from the hand. For most card games, you’d also want a method to sort the hand. Different card games would use different and/or ad- ditional Hand methods. We’ll keep things simple and not worry about them.
The next step is to try to identify common members and move them to a superclass. The Deck and Hand classes have three common members—a cards array variable, a currentSize variable, and a display method. In moving those members to a superclass, what would be a good name for such a class? It should be something generic that can be used as the superclass for both Deck and Hand. GroupOfCards or just plain Cards both sound pretty good. Let’s use GroupOfCards. In Figure 12.17’s class diagram, note the inheritance association lines connecting Deck to GroupOfCards and Hand to GroupOfCards.
We’ve now examined Athepmaemgbeors in aPll DfiveFclassEesninhtheaCnardcGeamre program, and we’ve examined the relationships between four of the classes—Game, Deck, Hand, and GroupOfCards. The last piece of the UML-class-diagram puzzle is the relationship between GroupOfCards and Card. Is it an is-a relationship or a has-a relationship? It’s not an is-a relationship because it doesn’t make sense to say that a group of cards is a card or a card is a group of cards. Instead, it’s a has-a relationship because a group of cards has a card (a group of cards usually has more than one card, but that doesn’t negate the has-a relationship). In Figure 12.17, note the has-a composition association line connecting GroupOfCards to Card. Figure 12.17 suggests implementing the composition as an array called cards, but it could be an ArrrayList
Note that Figure 12.17’s label says “preliminary” class diagram. It’s preliminary because for a decent- sized application, it’s nearly impossible to get the class diagram 100% right on your first-cut att
you’re done coding and testing(!) your prototype program, you should go back and update
your class diagram appropriately. The class diagram serves two purposes. Early in the design
process, it helps organize ideas and it keeps everybody on the same page. In the post-imple- mentation phase, it serves as documentation so interested parties can quickly get a handle on the application’s organization.
Inheritance Versus Composition
When deciding on the relationship between two classes, it’s usually pretty clear whether to use inheritance or composition. For example, in the Dealership program, a Manager is a Person, so inheritance is used. In the Card Game program, a Game has a Deck, so composition is used.
However, sometimes it’s not so clear-cut. For example, you could make the claim that a Deck is a GroupOfCards, and you could also make the claim that a Deck has a GroupOfCards. As a rule of thumb, in cases like this where the inheritance is-a relationship exists and the composition has-a relationship also exists, you’re better off going with the inheritance relationship. To see why, we’ll compare code for each
empt. When
Design is an iterative process.