Object Oriented Design of Card Deck I am designing classes for a game with card deck. Please review my code.


Each Player gets Hand of cards
The Deck can be shuffled and cards are dealt one at a time from the deck and added to the players hands.


Specifically, I am confused with the good method signature for the method dealCard in the Deck class. I can either pass the player method to the method like - void dealCard(Player player) or get the card and add to hand of player -  Card dealCard(). Which of these implementation is good as per the practices of OOPS? How do I think in these kind of scenarios? Any advice can be helpful

    package main;
        //Each card has a value and a suite.
    public class Card {
        int value;
        SUITE suite;

        public Card(int value, SUITE suite) {
            this.value = value;
            this.suite = suite;
        }

        public int getValue() {
            return value;
        }

        public SUITE getSuite() {
            return suite;
        }

        public void setValue(int value) {
            this.value = value;
        }

        public void setSuite(SUITE suite) {
            this.suite = suite;
        }

        @Override
        public String toString() {
            return "Card{" +
                    "value=" + value +
                    ", suite=" + suite +
                    '}';
        }
    }




package main;    
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class Deck {
    List&lt;Card&gt; cardDeck;

    public Deck() {
        this.cardDeck = new ArrayList&lt;Card&gt;();
        for(int value = 1 ; value &lt;= 13 ; value++){
            for(SUITE suite : SUITE.values()){
             cardDeck.add(new Card(value,suite));
            }
        }
    }

    @Override
    public String toString() {
        return "Deck{" +
                "cardDeck=" + cardDeck +
                '}';
    }

    public void shuffle(){
        Random rand = new Random();
        //Generate two random numbers between 0 to 51
        for(int i = 0 ; i &lt; 20 ; i ++){
            int firstCard = rand.nextInt(52);
            int secondCard = rand.nextInt(52);
            Collections.swap(cardDeck,firstCard,secondCard);
        }
    }

    public void dealCard(Player player){
       //Get next card and add to hand of the player
        Card removedCard = cardDeck.remove(0);
        player.getHand().add(removedCard);
    }

    public Card dealCard(){
        Card removedCard = cardDeck.remove(0);
        return removedCard;
    }

    //Size of the deck for testing purpose
    public int getSizeOfDeck(){
        return cardDeck.size();
    }
}




package main;    
import java.util.ArrayList;
import java.util.List;

public class Player {
    List&lt;Card&gt; hand;

    public Player() {
        this.hand = new ArrayList&lt;Card&gt;();
    }

    public List&lt;Card&gt; getHand() {
        return hand;
    }

    @Override
    public String toString() {
        return "Player{" +
                "hand=" + hand +
                '}';
    }
}




package main;

public enum SUITE {
    HEART,
    SPADE,
    CLUB,
    DIAMOND
}

package main;    
public class Main {
    public static void main(String args[]) {
        Deck deck = new Deck();
        System.out.println(deck);
        System.out.println("Size of deck is: "+deck.getSizeOfDeck());
        deck.shuffle();
        System.out.println("Deck after shuffling is "+deck);

        Player player1 = new Player();
        Player player2 = new Player();

        deck.dealCard(player1);
        System.out.println("Size of deck after dealing a card to player is "+deck.getSizeOfDeck());
        deck.dealCard(player2);
        System.out.println("Size of deck after dealing a card to player is "+deck.getSizeOfDeck());

        System.out.println("Hand of player 1 is "+player1.getHand());
        System.out.println("Hand of player 2 is "+player2.getHand());

        player1.getHand().add(deck.dealCard());
    }
}
So much to say, in so little space. This could be answered in so many ways, mainly due to why you need to model the cards. Without a proper context, the requirements will change and can thusly change the entire model. So lets pretend you're aiming to build one (or several) card game(s).

Separation of Concerns

There are many important OOP principles, but I'm mainly going to address the Separation of Concerns (or Concern related to Computer Science, as it often is what you need to consider first: Why do you have the classes/objects, and what is their intended purpose?    

Somewhat simplified one could say that: An object/class shouldn't need to concern itself with stuff outside of itself. This could allow for the internal of any class to be replaced, as long as the public API (the public methods to call it) aren't changed. I'm going to try to exemplify this related to the various classes you've provided.

Card

In other words, a Card shouldn't need to concern itself who might use it, and how they might use it. And the basic method of handling a card should remain somewhat constant.

More specific, it seems kind of strange that a Card is able to change its value or suit. What kind of a gaming card is able to do that? If it is the King of Diamonds, then it usually stays that way for ever. 

To me, it would be more natural for the cards to have a method defining how the output could look like. For example to choose alternative textual variations: "value: 13, suit: Spade", "King of Spade", "K♠" or even "". The last two examples from: Wikipedia's Playing Cards in Unicode.

Possibly the parent Card class should be rather empty, and allow for subclasses to specify the criteria of that card. Like ordinary playing cards, or a Uno deck, or Pokemon deck, and so on.

Deck

The Deck consists of Cards, but other than basic handling of cards, it shouldn't know too much about the cards. And it shouldn't really know anything about a Player or a Game using the Deck. 

And this answers your question on dealCard(). It shouldn't know anything about the player, and basically it should only remove a Card from the deck, and return it to whomever who might use it as they please. 

Other interesting functions for the Deck could be re-insert a card into the deck, possibly verifying that the card is legal in this kind of deck. Imaging solitaire games like Spider (using only the suite of Spade), or games using double decks.

Player, or maybe Hand?

I'm not sure what I would put in a Player class, but in the context of a card game, I think I would rather have a Hand class to describe my current set of cards. 

In this context, it would be natural to add/remove cards to the hand. And to display it in various alternatives. It could possibly have some generic methods for describing the order of a hand compared to another hand.

For subclassing one could also imagine that the hand could calculate the overall value of the hand, for example the Poker value, or whether it contained sets or series, I could imagine have methods for calculating the value of my hand, for example the Poker Hand value, or whether I had any series or sets. And the subclasses could specify which hands were the most valuable related to each other.

Code review


In general your code looks nice, with proper indentation and brace usage. I would prefer a little more consistency in commenting the methods/classes at a given place related to the definition. You could/should consider using Javadoc, or a given documentation standard for describing your classes.
A shuffle() method which only shuffles 20 cards, by swapping 2 each time, seems like a really lousy way to shuffle a deck. I'm sure you can do better than this. Maybe loop through the deck once, and switch the card placement to somewhere else in the deck?
Better presentation alternatives would be nice, I think. See comment on Card class above.
A minor detail on the SUIT enum. I would order it as SPADE, HEART, DIAMOND and CLUB, as that is the common ordering of value of cards in a lot of card games. Not entirely thrilled about the Uppercasing, but not sure what's the common method in Java to denote globals like these.


PS! I've used Wikipedia for reference, there does exist better description, but for consistency I chose to use these here.

PPS! Another interesting principle are the SOLID principle, but it might be difficult to wrap your head around if you're very new to programming.