Architecture – Is using Observer pattern a good idea while building a Chess Game

architectural-patternsArchitecturechessdesign-patternsobserver-pattern

I am trying to design a Chess Game using OOPs concepts that has a UI element to it. My idea is to show the number of squares / cells a piece can travel to when selected. Basically I want to show the paths / directions in which the it can travel / attack in a different color.

Some thing like the following

(enter image description here)

So I have designed an abstract Piece class, which among others, has a Map object that keeps track of all the cells to which it can travel direction-wise, something like this
Map<Direction, LinkedList<Cell>>

Now, say a Piece of the Queen's own team comes in its way of attack in the FORWARD direction and puts itself on the cell that's located at chessBoard[6][4]

What best way can I notify the Queen or any other piece watching that particular cell of the event so that each piece can call its own update method and redraw its path of attack?

I was thinking of going with the Observer pattern where every cell will be a subject and only the pieces watching them will be observers. So in any case anything happens in any of the cells watched by a particular set of pieces, only those pieces will be notified.

But then I am not sure if this is a good approach as I have to have at max 32 listeners for every cell. Not sure if it will be scalable at all.

Are there any better ways to do it?

Thanks for taking the time to read.

Best Answer

Having a "Map object that keeps track of all the cells to which it can travel" looks to me like an example of premature optimization.

Instead of remembering all those cells for each piece "just in case it could become slow", why not give a piece a method with the board as parameter, which returns the related List<Cell> (or Map<Direction, LinkedList<Cell>>) by calculating it when the method is called? This way, no notifications or observer pattern or "32 listeners" are needed any more. It may be debatable if it should really be a method of the piece, or a method of the board. However, if you put this method into the board instead of the piece, pieces will not have to know anything about the board, so this avoids a cyclic dependency between boards and pieces.

If it turns out later that this method is called quite often for the same, unchanged board so it becomes a performance bottleneck (which I doubt), you can still cache its results using memoization. That would lead to a solution where a Map<Direction, LinkedList<Cell>> per piece is required, but without the necessity of actively observing other board changes.