In my board game I want to decouple my Player
and Board
class since I've changed piece moving system several times now and it's been a chore each time. I think I could use some interface for taking a player request to alter the board state but I can't decide if a Command or a Mediator interface is the appropriate solution (or even Observer?)
My understanding is that a Command executes something a that a client wishes to do to a receiver while not knowing how they do it. But does a Mediator not do mostly the same thing? You specify a request object and the mediator executes the requests on client behalf? Does the Mediator facilitate two-way communication e.g. can a player request to move a piece and if successful, can the board in turn notify the player of the new board state?
Basically, I'm having trouble knowing which way to decouple my classes between 3 seemingly related patterns. I've read the GoF discussion on this and I'm still confused since they don't use concrete examples of when they'd be more useful than one another.
1 Answer 1
Is it the right question ?
The Mediator
is about the interactions between "colleague" objects who don't know each other. The Command
is about how to execute one specific interaction (whether the command is created by a Player or by a mediator). The question should therefore not about which alternative to use, but how each of them could serve your purpose.
How could the Mediator help ?
The purpose of the mediator pattern is to encapsulate the interaction between several colleague objects in order to isolate them from each other. Using the mediator to decouple a Player
and a Board
would make the design a little complex:
Player
andBoard
would implement the same commonColleague
interfacePlayer
sends move requests toMediator
Mediator
knows that player requests are to be sent toBoard
Board
receives request fromMediator
Board
analyses request and informsMediator
that it was accepted (or rejected)Mediator
knows that these kind of interaction are to be sent toPlayer
Player
receives answer fromMediator
Furthermore, as stated in GoF, it could be useful to make Mediator an observer to the different colleagues, so that it is informed of relevant state changes and can trigger actions.
The advantage of this more complex approach is its flexibility: you could have 2 Players
and a Board
for example. You could add a timer Colleague
. You could add an adviser/coach Colleague
to inform the human player of how good his move is (or provide similar information to a machine learning AI player).
Furthermore, as the colleagues are decoupled, you could potentially reuse them in other games.
What about the Command ?
The purpose of the command pattern is to encapsulate requests. So you'd encapsulate the moves for the board and let them be executed (or reversed in case the user activates an undo).
You'd certainly use an observer pattern, to let the Player
observe the Board
state change. And may be a second Player
(AI or human) would also subscribe to the Board
change and issue commands to trigger moves. And you'd certainly have a main loop for the game, in which you could add a timer.
In the end, you would have a similar structure (game loop glues together the pieces). However, the objects need to know each other, and a change in the interaction between the objects might require adaptations of all the involved classes.
Recommendations
- If you want to allow an undo, you'd better use the
Command
. - If you have only two colleagues, the mediator seems a little over-engineered if you only have a single game. It further may constraint the rest of the design. So maybe start without it and refactor the code when you have something working.
- If you're interested in game coding in general, Mike McShaffry's book "Game Coding Complete" is for you : he explains how to structure a game, the challenges, and the pitfalls to avoid. There's not much theory about patterns, but a lot of common sense about working game architectures.
-
1Very good answer. Small note: it is not necessary that all colleagues implement a common
Colleague
interface. In the GoF book this is just coincidental since they're talking about a GUI widget hierarchy. There is no dependency on this interface. It's just important that each colleague holds a reference to the mediator in order to initiate events. Here, the Board and Player would generate completely different kinds of events and should not share an interface.amon– amon01/18/2018 13:30:26Commented Jan 18, 2018 at 13:30
Explore related questions
See similar questions with these tags.
undo
methods and state as well to the command interface so that the opposite action can be performed.undo
potential in aMoveCommand
is going to be useful for me. Follow up question: Could a command object reference strategy objects? Like if a player moves a certain piece, the specific move behavior is dependent on the type of piece being moved, each move type being encapsualted in a strategy object