Lets focus on the obvious advantage first: in the first example, the controllers are mostly independent from each other. PlayerSelectCharacterController
does not need to know about the class CharacterMoveController
or vice versa. Each of these classes can be developed separately, tested separately, or if necessary, placed in different compilation units.
That is not possible in the second example: PlayerSelectCharacterController
needs to know about CharacterMoveController
, this is a hardcoded dependency.
With just two classes, this may not be worth to think about, but if your game has 20 or more states, you will easily get a huge dependency tree, where every controller depends on every other controller, maybe in some cyclic way.
What may be less obvious: in games, state transitions are often not that simple as in your question's example. There might be complex rules how to change from one state to another. For a certain kind of complexity, it may be desirable to separate the two concerns of
- deciding about the new state, and
- actually changing the state.
I would actually expect the logic you showed us in characterSelected
to be happen somewhere outside the PlayerSelectCharacterController
, maybe in the parentController
(characterSelected
maybe a function returning the new state, but the assignment to globalData should not happen directly in PlayerSelectCharacterController
). That would also avoid the need to call parentController.stateChanged()
from within PlayerSelectCharacterController
, this could be done by the outer loop, which can prevent some potential problems with recursion as well as code duplication.
As a general strategy, try to build the individual controllers as separate building blocks, with no side effects to global data, and no direct dependencies to other controllers of the same kind. Otherwise you risk getting an unmaintainable "big ball of mud".