Java – Proper OO design for State and Command

designjavaobject-oriented

I'm working (a bit) on a (turn-based strategy) game. There are two classes relevant for the question:

  • State: This is an immutable class, which exposes all its fields (either via getters or another way, as I felt appropriate). The state is a bit complicated, so I decomposed it into several classes in the package ...state
  • Command: This is an abstract immutable class with a couple of subclasses like MoveCommand(Field from, Field to), PassCommand(), BidCommand(int amount), etc. in the package ...command. All of fields have public getters.

I need one of the two methods

  • State Command.applyTo(State) or
  • State State.apply(Command)

returning the new state (obtained by applying the command to the state).

Using the first method looks better at the first sight, since it dispatches to different implementations of applyTo in the subclasses of Command. Unfortunately, it forces me to fiddle with the many details of State in the class Command. In order to make it work, I need something like MutableState, or State.Builder, or a many-args constructor of State, or whatever.

Using the second method looks ugly, as it'd force me to use instanceof (or some other ugly way to simulate the virtual method dispatch). OTOH, it would concentrate the working with State in the class itself.

So I think the first method is the way to go. With Command and State each in its own package it means that MutableState (or whatever gets used for building the resulting State) need to be a public class since there are no friends in Java. No real problem, but not nice, is it?

So what is the proper design?

Best Answer

Don't get too caught up on the State Pattern. This has a specific usage which I don't think necessarily applies in your game, at least not when you are manipulating the state of play.

Take, for example, a drawing application. In this case, the button pressed in the toolbar affects the way the drawing panel reacts to certain stimuli -- in this case, you don't want the application to know what it is going to do, you just want it to pass the stimulus to the State object and let it figure out what to do.

So, the rectangle drawing button is down, the application holds a RectangleDrawingState from which it can request a mouse-over pointer type or a mouse-down action or whatever. If you press the elipse-drawing button then that control switches out the RectangleDrawingState for an ElipseDrawingState and the application continues to ask for a mouse-over pointer type and a mouse-down action and gets completely different responses.

This is the kind of situation that makes for a good use-case for the State Pattern.

Now you may want this in your turn-based strategy game, to handle whether the attack button is pressed or the gather resources button is pressed. But you should handle the state of the game differently.

The state of the game should be handled as a single mutable object, which is manipulated at the end of each action. This object needs to be serializable in some form.

What you should do then is get a Command object by whatever means necessary and act on the mutable state-of-play object (it might be that your immutable State object, which depends on the action selected at any given time, returns a command which can act on the state-of-play object, for example).

Related Topic