petabyte
petabyte

Reputation: 1567

How to remove the circular dependency from this use of the Strategy pattern?

I'm trying to grok the Strategy pattern and came up with the following example:

But if we have Board, Piece, and MoveBehavior objects

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

Answers (2)

oɔɯǝɹ
oɔɯǝɹ

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

TheLethalCoder
TheLethalCoder

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 Boards responsibility.

Upvotes: 1

Related Questions