Reputation: 1567
I'm trying to grok the Strategy pattern and came up with the following example:
But if we have Board
, Piece
, and MoveBehavior
objects
Board
-> Piece
because a Board
contains Piece
sPiece
-> Board
because a piece needs to pass in the Board
as a param to
MoveBehavior
which needs the Board
to decide what moves are acceptable.How can we get rid of this circular dependency? Also, isn't this a common problem in more realistic examples because behaviors need large enough state to make decisions? I think if the behavior is super simple it's not that big a deal to not use the Strategy pattern.
Upvotes: 4
Views: 670
Reputation: 7625
It sounds like you can use a dependency injection framework to resolve all the object instances. You will need a configurable container if you want to use different combinations of types to instantiate. You could call the configurable container a strategy (as it selects all the pieces that come into play).
I would not make the board responsible for creating all the pieces and behaviors, but rather use a composer class (that uses dependency injection) for that.
This allows you (for example) to use behaviors for the board, or to create different board types as well.
See also this question and answer for some background on how dependency injection helps to obtain loose coupling.
Upvotes: 3
Reputation: 6744
I'd just use Board
-> Piece
-> MoveBehaviour
.
The reason being is that the board contains the pieces and the pieces have their own move behaviour depending on what type they are.
MoveBehaviour
tells the piece its allowed movements i.e. (example is C# because that is what I am familiar with)
public Move[] Moves
{
get
{
return new Move[] { Move.Horizontal, Move.Vertical };
}
}
The job of MoveBehaviour
is not to see if the Piece
can move to where it is requesting that is the board.
More easily explained in the below C# example:
public class Board
{
public List<Piece> Pieces { get; set; }
public bool CanMoveTo(Piece piece, Point location) { /*...*/ }
}
public class Piece : IMoveBehaviour
{
public Move[] Moves { get; set; }
}
public interface IMoveBehaviour
{
Move[] moves { get; set; }
}
And with methods in Board
and Piece
like RequestMove
, Move
, IsValidMove
etc...
Essentially leave the responsibility of something to that something and do not move it around. MoveBehaviour
is the behaviour of a Piece
not the validation of the moves that is the Board
s responsibility.
Upvotes: 1