jmrah
jmrah

Reputation: 6222

Is there any way to 'limit' the methods that can be called on a class depending on the current state of a program?

Say I am developing a very simple card game. The card game has two phases.

1st Phase: Everone draws a card in turn order. 2nd Phase: Everyone plays a card, in turn order.

So, I model the game with an api that looks like this:

public class Game {
    public void draw(PlayerId playerId) {
        Player player = players.get(playerId);
        player.drawFrom(drawDeck);
    }

    public void play(PlayerId playerId, CardId cardId) {
        Player player = players.get(playerId);
        player.playCard(cardId);
    }
}

Here is my problem: the Game class has two methods to call, but only one method is valid at any one particular time. If the game is in the first phase, then the method play shouldn't be called. Likewise, if the game is in the second phase, the method draw should not be called.

What options do I have in this situation? I can only think of throwing exceptions if methods are called when they shouldn't be.

Ideally, I would like the client code to only be able to call the methods that are valid at that particular time. Any ideas on how I can do this? Or should the onus be on the client to call the methods correctly?

Upvotes: 2

Views: 29

Answers (3)

Kevin Condon
Kevin Condon

Reputation: 1728

The Strategy design pattern can help here. Define a Game interface with GamePhase1 and GamePhase2 implementations.

public interface Game {
    public boolean isDrawAllowed();
    public boolean isPlayAllowed();
    public void draw(...);
    public void play(...);
}

Each implementation would return the appropriate booleans for the game phase. Invalid draw or play methods could throw an exception. The managing code would swap in the proper implementation as game phase changes. Checking the is... methods would avoid encountering the exceptions and allow a UI to choose what options to display.

Upvotes: 2

Chris Chambers
Chris Chambers

Reputation: 1365

You can use exception handling, but you can also just use an if statement and print a message.

I assume this game has a client server model, and that you are concerned that somebody could modify their client to try and do inappropriate actions. I would handle this in the methods that call the methods you described like so:

public class Main {
    public void takeNextTurn(PlayerId playerId, int action)
      if(action == 0){
         if (appropriate_to_draw){
            game.draw(playerid);
         }
         else {
            messageClient("You can't draw now");
         }
         ...
      }
   }

In your client, make sure you handle this message.

Upvotes: 0

dkatzel
dkatzel

Reputation: 31648

You should use the State Pattern and break the interface into 2 separate DrawPhase and PlayPhase where each only has the one valid method. Your Game class can then change what phase it is based on the rules of the game you're implementing.

Upvotes: 1

Related Questions