1
\$\begingroup\$

PawnMovement ... KingMovement are of type Movement. This is implementation of strategy pattern. Basing on actual value of PieceType I want to choose proper strategy. How to avoid long if/else statements or switch?

    PieceType pieceType;
    if(this.board.getPieceAt(from) != null) {
        pieceType = this.board.getPieceAt(from).getType();
    } else {
        throw new InvalidMoveException();
    }

    if (pieceType == PieceType.PAWN) {
        contextMovement.setContext(new PawnMovement());
    } else if (pieceType == PieceType.ROOK) {
        contextMovement.setContext(new RookMovement());
    } else if (pieceType == PieceType.KNIGHT) {
        contextMovement.setContext(new KnightMovement());
    } else if (pieceType == PieceType.BISHOP) {
        contextMovement.setContext(new BishopMovement());
    } else if (pieceType == PieceType.QUEEN) {
        contextMovement.setContext(new QueenMovement());
    } else if (pieceType == PieceType.KING) {
        contextMovement.setContext(new KingMovement());
    }
    return contextMovement.executeMovement(from, to, board);
\$\endgroup\$
3
\$\begingroup\$

The complexity of approach is too high, it can be reduced to the following:

PieceType pieceType = getPieceType();
contextMovement.setContext(pieceType.getMovement());
return contextMovement.executeMovement(from, to, board);

The PieceType enum (probably call it Piece?) can be extended with:

public enum Piece {

  PAWN() {
    @Override
    public Movement getMovement() { 
      return new PawnMovement();
    }
  }, ... // other elements;

  public abstract Movement getMovement();

}
\$\endgroup\$
1
\$\begingroup\$

Obviously the information carried by PieceType is tightly coupled to the possible movement. This is not due to your coding, it's due to the modelled domain.

In a somewhat common case I came with a solution that reflects the coupling of domain artifacts in code. I hooked up the functionality to the enum:

enum Strategy {
    SQUARE() {
        public int perform(int arg) {
            return arg * arg;
        }
    },
    TRIPLE() {
        public int perform(int arg) {
            return 3 * arg;
        }
    };
    abstract public int perform(int arg);
}

Elsewhere in your code you just hand the instrumented enum value around and all functionality is at hand.

int performWith(Strategy s, int i) {
    ...
    return s.perform(i);
}
\$\endgroup\$
0
\$\begingroup\$

Some suggestions:

  • Have each piece implement the type of movement it makes. This means each piece inherits from Movement class so you can just call something like piece.getMovementContext()

  • Store the movement for each piece in an EnumMap and do a look up of the movement depending on the piece.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.