Problem
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);
Solution
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();
}
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);
}
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 likepiece.getMovementContext()
-
Store the movement for each piece in an
EnumMap
and do a look up of the movement depending on the piece.