I am creating a board game (such as chess) in Java, where each piece is its own type (like Pawn
, Rook
etc.). For the GUI part of the application I need an image for each of these pieces. Since doing thinks like
rook.image();
violates separation of UI and business logic, I will create a different presenter for each piece and then map the piece types to their corresponding presenters like
private HashMap<Class<Piece>, PiecePresenter> presenters = ...
public Image getImage(Piece piece) {
return presenters.get(piece.getClass()).image();
}
So far so good. However, I sense a prudent OOP guru would frown upon calling a getClass()
method and would suggest using a visitor for example like this:
class Rook extends Piece {
@Override
public <T> T accept(PieceVisitor<T> visitor) {
return visitor.visitRook(this);
}
}
class ImageVisitor implements PieceVisitor<Image> {
@Override
public Image visitRook(Rook rook) {
return rookImage;
}
}
I like this solution (thank you, guru), but it has one significant drawback. Every time a new piece type is added to the application the PieceVisitor needs to be updated with a new method. I would like to use my system as a board game framework where new pieces could be added through a simple process where the user of the framework would only provide implementation of both the piece and its presenter, and simply plug it into the framework. My question: is there a clean OOP solution without instanceof
, getClass()
etc. which would allow for this kind of extensibility?
setType(ChessPieceType.QUEEN)
, but with inheritance you need to create an entirely newPiece
object). I generally find implementation inheritance to not be very useful, and much prefer techniques using aggregates of objects instead. – Jules May 25 '17 at 03:26public Image visitRook(Rook rook)
when instead you could have done something likepublic Image visitPiece(Rook rook)
and have similar overloaded methods such asvisitPiece(King kind)
in which case you could dispense of theaccept
method on thePiece
side? – Mehdi Charife Sep 12 '23 at 20:34