I am trying to design a Chess game where each piece of the game inherits from an abstract Piece
class.
The piece just does a few things:
- It tells which color it is (White / Black)
- It tells what type it is
- It tells if a move is valid or not
- and maybe what cell / square on the board it is currently at
Earlier I was thinking of making the validation a part of the piece itself so that there would be an abstract validateMove()
method that each piece would have to implement, but then this might lead to a lot of code changes if, in future, I decide to change the move validation mechanism of a specific piece, something similar to the case of Rubber duck with no fly method described in the Head First Design book.
Hence, I thought of creating this interface called MoveValidator, which would have piece-specific implementations and each piece would have a validator as one of its variables rather than being a validator itself or implementing the validation itself.
So a Pawn
would have a PawnMoveValidator
as one of its composition.
So I have the following abstract Piece class
@RequiredArgsConstructor
public abstract class Piece {
@NonNull
@Getter
private final PieceColor pieceColor;
@NonNull
@Getter
private final MoveValidator moveValidator;
@Getter
@Setter
private Point currentLocation;
private boolean basicValidation(Cell[][] board, Point src, Point dest) {
.........
.........
}
public boolean validateMove(Cell[][] board, Point src, Point dest) {
return basicValidation(board, src, dest) && moveValidator.validateMove(board, src, dest);
}
}
Cell.java
@RequiredArgsConstructor
public class Cell {
@NonNull
@Getter
private final CellColor cellColor;
@NonNull
@Getter
private final Integer row;
@NonNull
@Getter
private final Integer col;
}
Point.java
@RequiredArgsConstructor
public class Point {
@NonNull
@Getter
private final Integer x;
@NonNull
@Getter
private final Integer y;
}
MoveValidator.java
public interface MoveValidator {
validateMove(Cell[][] board, Point src, Point dest);
}
So I have a few questions here.
- Is this a good design or can this be improved further?
- If the
Piece
doesn't have any abstract method to implement, should it still remain an abstract class or should it become a concrete class? - What if the move validation of a specific piece requires the knowledge of the state of that specific piece for which it's implemented?
For ex: The pawn wants to move two cells ahead. The
Pawn
class has a flag telling whether it's the first move or not. In that case, if thePawnMoveValidator
wanted to validate the move, it would need to know the state of the flag. How can that be possible without making the Pawn class implement the validator itself?
Thanks for your time