Questions and Answers

Q: Why code the state as objects?
Q: Isn't it simpler to code the state as a number? We can just increment when we win, and reset to zero when we lose.
Q: Doesn't this create a vast number of state objects?
Q: Is Polymorphism necessary?
Q:

Why code the state as objects?

A:

The reason for encoding the states as objects is to encapsulate the information or behavior associated with that state. In this case, we have both the bet amount and the rules for transition to next state. While simple, these are still unique to each state.

Since this is a book on design, we feel compelled to present the best design. In games like blackjack, the player's state may have much more complex information or behavior. In those games, this design pattern will be very helpful. In this one case only, the design pattern appears to be over-engineered.

We will use this same design pattern to model the state changes in the Craps game itself. In the case of the Craps game, there is additional information as well as behavior changes. When the state changes, bets are won or lost, bets are working or not, and outcomes are allowed or prohibited.

Q:

Isn't it simpler to code the state as a number? We can just increment when we win, and reset to zero when we lose.

A:

The answer to all “isn't it simpler” questions is “yes, but...”. In this case, the full answer is “yes, but what happens when you add a state or the states become more complex?

This question arises frequently in OO programming. Variations on this question include “Why is this an entire object?” and “Isn't an object over-engineering this primitive type?” See Why is Outcome a separate class? Each object that is an instance of Outcome only has two attributes; why not use an array of Strings for the names, and a parallel array of integers for the odds? FAQ entry on the Outcome class for additional background on this.

Our goal in OO design is to isolate responsibility. First, and most important, we can unambiguously isolate the responsibilities for each individual state. Second, we find that it is very common that only one state changes, or new states get added. Given these two conditions, the best object model is separate state objects.

Q:

Doesn't this create a vast number of state objects?

A:

Yes.

There are two usual follow-up questions: “Aren't all those objects a lot of memory overhead?” or “...a lot of processing overhead?

Since Java and Python remove unused objects, the old state definitions are cleaned up by the garbage collection thread. A few tests will demonstrate that the Java memory management is efficient and reliable.

Object creation is an overhead that we can control. One common approach is to use the Singleton design pattern. In this case, this should be appropriate because we only want a single instance of each of these state classes.

Note that using the Singleton design pattern doesn't change any interfaces except the initialization of the Player1326 object with the starting state.

Q:

Is Polymorphism necessary?

A:

In some design patterns, like State and Command, it is essential that all subclasses have the same interface and be uniform, indistinguishable, almost anonymous instances. Because of this polymorphic property, the objects can be invoked in a completely uniform way.

In our exercise, we will design a number of different states for the player. Each state has the same interface. The actual values for the instance variables and the actual operation implemented by a subclass method will be unique. Since the interfaces are uniform, however, we can trust all state objects to behave properly.

There are numerous designs where polymorphism doesn't matter at all. In many cases, the anonymous uniformity of subclasses isn't relevant. When we move on to example other casino games, we will see many examples of non-polymorphic class hierarchies. This will be due to the profound differences between the various games and their level of interaction with the players.