refactor OutputSystem

This commit is contained in:
2025-04-12 11:12:36 +02:00
parent 0d3d77781f
commit 8190090adc
19 changed files with 176 additions and 49 deletions

View File

@@ -9,7 +9,7 @@ import chess.model.ChessBoard;
import chess.model.Game; import chess.model.Game;
import chess.view.consolerender.Console; import chess.view.consolerender.Console;
public class App { public class ConsoleMain {
public static void main(String[] args) { public static void main(String[] args) {
CommandExecutor commandExecutor = new CommandExecutor(); CommandExecutor commandExecutor = new CommandExecutor();
@@ -17,7 +17,7 @@ public class App {
Console console = new Console(commandExecutor); Console console = new Console(commandExecutor);
commandExecutor.setGame(game); commandExecutor.setGame(game);
commandExecutor.setOutputSystem(console); commandExecutor.addListener(console);
commandExecutor.executeCommand(new NewGameCommand()); commandExecutor.executeCommand(new NewGameCommand());
} }

View File

@@ -0,0 +1,21 @@
package chess;
import chess.controller.CommandExecutor;
import chess.controller.commands.NewGameCommand;
import chess.model.ChessBoard;
import chess.model.Game;
import chess.view.simplerender.Window;
public class SwingMain {
public static void main(String[] args) {
CommandExecutor commandExecutor = new CommandExecutor();
Game game = new Game(new ChessBoard());
Window window = new Window(commandExecutor);
commandExecutor.setGame(game);
commandExecutor.addListener(window);
commandExecutor.executeCommand(new NewGameCommand());
}
}

View File

@@ -1,5 +1,6 @@
package chess.controller; package chess.controller;
import chess.controller.event.GameListener;
import chess.model.Game; import chess.model.Game;
public abstract class Command { public abstract class Command {
@@ -15,7 +16,7 @@ public abstract class Command {
NotAllowed; NotAllowed;
} }
public abstract CommandResult execute(Game game, OutputSystem outputSystem); public abstract CommandResult execute(Game game, GameListener outputSystem);
public void postExec(Game game, OutputSystem outputSystem) {} public void postExec(Game game, GameListener outputSystem) {}
} }

View File

@@ -2,24 +2,25 @@ package chess.controller;
import chess.controller.Command.CommandResult; import chess.controller.Command.CommandResult;
import chess.controller.commands.UndoCommand; import chess.controller.commands.UndoCommand;
import chess.controller.event.GameDispatcher;
import chess.controller.event.GameListener;
import chess.model.Game; import chess.model.Game;
import chess.model.Game.GameStatus; import chess.model.Game.GameStatus;
public class CommandExecutor { public class CommandExecutor {
private Game game; private Game game;
private OutputSystem outputSystem; private final GameDispatcher dispatcher;
public CommandExecutor() { public CommandExecutor() {
this.game = null; this.game = null;
this.outputSystem = null; this.dispatcher = new GameDispatcher();
} }
public synchronized CommandResult executeCommand(Command command) { public synchronized CommandResult executeCommand(Command command) {
assert this.game != null : "No input game specified !"; assert this.game != null : "No input game specified !";
assert this.outputSystem != null : "No output system specified !";
CommandResult result = command.execute(this.game, this.outputSystem); CommandResult result = command.execute(this.game, this.dispatcher);
// non player commands are not supposed to return move result // non player commands are not supposed to return move result
assert result != CommandResult.Moved || command instanceof PlayerCommand || command instanceof UndoCommand; assert result != CommandResult.Moved || command instanceof PlayerCommand || command instanceof UndoCommand;
@@ -29,7 +30,7 @@ public class CommandExecutor {
if (command instanceof PlayerCommand playerCommand && result != CommandResult.NotAllowed) if (command instanceof PlayerCommand playerCommand && result != CommandResult.NotAllowed)
this.game.addAction(playerCommand); this.game.addAction(playerCommand);
command.postExec(game, outputSystem); command.postExec(game, dispatcher);
return result; return result;
} }
@@ -40,21 +41,21 @@ public class CommandExecutor {
return; return;
case ActionNeeded: case ActionNeeded:
this.outputSystem.updateDisplay(); this.dispatcher.updateDisplay();
return; return;
case Moved: case Moved:
if (checkGameStatus()) if (checkGameStatus())
return; return;
switchPlayerTurn(); switchPlayerTurn();
this.outputSystem.updateDisplay(); this.dispatcher.updateDisplay();
return; return;
} }
} }
private void switchPlayerTurn() { private void switchPlayerTurn() {
this.game.switchPlayerTurn(); this.game.switchPlayerTurn();
this.outputSystem.playerTurn(this.game.getPlayerTurn()); this.dispatcher.playerTurn(this.game.getPlayerTurn());
} }
/** /**
@@ -66,27 +67,27 @@ public class CommandExecutor {
switch (gameStatus) { switch (gameStatus) {
case Check: case Check:
this.outputSystem.kingIsInCheck(); this.dispatcher.kingIsInCheck();
return false; return false;
case CheckMate: case CheckMate:
this.outputSystem.kingIsInMat(); this.dispatcher.kingIsInMat();
this.outputSystem.winnerIs(this.game.getPlayerTurn()); this.dispatcher.winnerIs(this.game.getPlayerTurn());
return true; return true;
case OnGoing: case OnGoing:
return false; return false;
case Pat: case Pat:
this.outputSystem.patSituation(); this.dispatcher.patSituation();
return true; return true;
} }
return false; return false;
} }
public void setOutputSystem(OutputSystem outputSystem) { public void addListener(GameListener listener) {
this.outputSystem = outputSystem; this.dispatcher.addListener(listener);
} }
public void setGame(Game game) { public void setGame(Game game) {

View File

@@ -1,14 +1,15 @@
package chess.controller; package chess.controller;
import chess.controller.event.GameListener;
import chess.model.Game; import chess.model.Game;
public abstract class PlayerCommand extends Command{ public abstract class PlayerCommand extends Command{
public CommandResult undo(Game game, OutputSystem outputSystem) { public CommandResult undo(Game game, GameListener outputSystem) {
CommandResult result = undoImpl(game, outputSystem); CommandResult result = undoImpl(game, outputSystem);
game.updateLastMove(); game.updateLastMove();
return result; return result;
} }
protected abstract CommandResult undoImpl(Game game, OutputSystem outputSystem); protected abstract CommandResult undoImpl(Game game, GameListener outputSystem);
} }

View File

@@ -1,7 +1,7 @@
package chess.controller.commands; package chess.controller.commands;
import chess.controller.OutputSystem;
import chess.controller.PlayerCommand; import chess.controller.PlayerCommand;
import chess.controller.event.GameListener;
import chess.model.ChessBoard; import chess.model.ChessBoard;
import chess.model.Color; import chess.model.Color;
import chess.model.Coordinate; import chess.model.Coordinate;
@@ -19,7 +19,7 @@ public class CastlingCommand extends PlayerCommand {
} }
@Override @Override
public CommandResult execute(Game game, OutputSystem outputSystem) { public CommandResult execute(Game game, GameListener outputSystem) {
final ChessBoard board = game.getBoard(); final ChessBoard board = game.getBoard();
// we must promote the pending pawn before // we must promote the pending pawn before
@@ -53,7 +53,7 @@ public class CastlingCommand extends PlayerCommand {
} }
@Override @Override
protected CommandResult undoImpl(Game game, OutputSystem outputSystem) { protected CommandResult undoImpl(Game game, GameListener outputSystem) {
game.getBoard().undoMove(this.kingMove, null); game.getBoard().undoMove(this.kingMove, null);
game.getBoard().undoMove(this.rookMove, null); game.getBoard().undoMove(this.rookMove, null);

View File

@@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import chess.controller.Command; import chess.controller.Command;
import chess.controller.OutputSystem; import chess.controller.event.GameListener;
import chess.model.ChessBoard; import chess.model.ChessBoard;
import chess.model.Coordinate; import chess.model.Coordinate;
import chess.model.Game; import chess.model.Game;
@@ -21,7 +21,7 @@ public class GetAllowedMovesPieceCommand extends Command {
} }
@Override @Override
public CommandResult execute(Game game, OutputSystem outputSystem) { public CommandResult execute(Game game, GameListener outputSystem) {
final ChessBoard board = game.getBoard(); final ChessBoard board = game.getBoard();
Piece piece = board.pieceAt(start); Piece piece = board.pieceAt(start);

View File

@@ -1,7 +1,7 @@
package chess.controller.commands; package chess.controller.commands;
import chess.controller.Command; import chess.controller.Command;
import chess.controller.OutputSystem; import chess.controller.event.GameListener;
import chess.model.Coordinate; import chess.model.Coordinate;
import chess.model.Game; import chess.model.Game;
import chess.model.Piece; import chess.model.Piece;
@@ -17,7 +17,7 @@ public class GetPieceAtCommand extends Command{
} }
@Override @Override
public CommandResult execute(Game game, OutputSystem outputSystem) { public CommandResult execute(Game game, GameListener outputSystem) {
if (!pieceCoords.isValid()) if (!pieceCoords.isValid())
return CommandResult.NotAllowed; return CommandResult.NotAllowed;

View File

@@ -3,7 +3,7 @@ package chess.controller.commands;
import java.util.List; import java.util.List;
import chess.controller.Command; import chess.controller.Command;
import chess.controller.OutputSystem; import chess.controller.event.GameListener;
import chess.model.Game; import chess.model.Game;
import chess.model.Move; import chess.model.Move;
@@ -12,7 +12,7 @@ public class GetPlayerMovesCommand extends Command {
private List<Move> moves; private List<Move> moves;
@Override @Override
public CommandResult execute(Game game, OutputSystem outputSystem) { public CommandResult execute(Game game, GameListener outputSystem) {
this.moves = game.getBoard().getAllowedMoves(game.getPlayerTurn()); this.moves = game.getBoard().getAllowedMoves(game.getPlayerTurn());
return CommandResult.NotMoved; return CommandResult.NotMoved;
} }

View File

@@ -1,7 +1,7 @@
package chess.controller.commands; package chess.controller.commands;
import chess.controller.OutputSystem;
import chess.controller.PlayerCommand; import chess.controller.PlayerCommand;
import chess.controller.event.GameListener;
import chess.model.ChessBoard; import chess.model.ChessBoard;
import chess.model.Coordinate; import chess.model.Coordinate;
import chess.model.Game; import chess.model.Game;
@@ -24,7 +24,7 @@ public class MoveCommand extends PlayerCommand {
} }
@Override @Override
public CommandResult execute(Game game, OutputSystem outputSystem) { public CommandResult execute(Game game, GameListener outputSystem) {
final ChessBoard board = game.getBoard(); final ChessBoard board = game.getBoard();
// we must promote the pending pawn before // we must promote the pending pawn before
@@ -58,7 +58,7 @@ public class MoveCommand extends PlayerCommand {
} }
@Override @Override
protected CommandResult undoImpl(Game game, OutputSystem outputSystem) { protected CommandResult undoImpl(Game game, GameListener outputSystem) {
final ChessBoard board = game.getBoard(); final ChessBoard board = game.getBoard();
board.undoMove(move, deadPiece); board.undoMove(move, deadPiece);
@@ -66,11 +66,11 @@ public class MoveCommand extends PlayerCommand {
} }
@Override @Override
public void postExec(Game game, OutputSystem outputSystem) { public void postExec(Game game, GameListener outputSystem) {
tryPromote(game, outputSystem); tryPromote(game, outputSystem);
} }
private void tryPromote(Game game, OutputSystem outputSystem) { private void tryPromote(Game game, GameListener outputSystem) {
Coordinate pawnPos = game.getBoard().pawnPromotePosition(); Coordinate pawnPos = game.getBoard().pawnPromotePosition();
if (pawnPos == null) if (pawnPos == null)

View File

@@ -1,7 +1,7 @@
package chess.controller.commands; package chess.controller.commands;
import chess.controller.Command; import chess.controller.Command;
import chess.controller.OutputSystem; import chess.controller.event.GameListener;
import chess.model.ChessBoard; import chess.model.ChessBoard;
import chess.model.Color; import chess.model.Color;
import chess.model.Coordinate; import chess.model.Coordinate;
@@ -14,7 +14,7 @@ import chess.model.pieces.Queen;
import chess.model.pieces.Rook; import chess.model.pieces.Rook;
public class NewGameCommand extends Command { public class NewGameCommand extends Command {
public CommandResult execute(Game game, OutputSystem outputSystem) { public CommandResult execute(Game game, GameListener outputSystem) {
final ChessBoard board = game.getBoard(); final ChessBoard board = game.getBoard();
board.clearBoard(); board.clearBoard();

View File

@@ -1,7 +1,7 @@
package chess.controller.commands; package chess.controller.commands;
import chess.controller.OutputSystem;
import chess.controller.PlayerCommand; import chess.controller.PlayerCommand;
import chess.controller.event.GameListener;
import chess.model.ChessBoard; import chess.model.ChessBoard;
import chess.model.Color; import chess.model.Color;
import chess.model.Coordinate; import chess.model.Coordinate;
@@ -33,7 +33,7 @@ public class PromoteCommand extends PlayerCommand {
} }
@Override @Override
public CommandResult execute(Game game, OutputSystem outputSystem) { public CommandResult execute(Game game, GameListener outputSystem) {
final ChessBoard board = game.getBoard(); final ChessBoard board = game.getBoard();
this.pieceCoords = board.pawnPromotePosition(); this.pieceCoords = board.pawnPromotePosition();
@@ -78,7 +78,7 @@ public class PromoteCommand extends PlayerCommand {
} }
@Override @Override
protected CommandResult undoImpl(Game game, OutputSystem outputSystem) { protected CommandResult undoImpl(Game game, GameListener outputSystem) {
final ChessBoard board = game.getBoard(); final ChessBoard board = game.getBoard();
Piece promoted = board.pieceAt(this.pieceCoords); Piece promoted = board.pieceAt(this.pieceCoords);

View File

@@ -1,7 +1,7 @@
package chess.controller.commands; package chess.controller.commands;
import chess.controller.Command; import chess.controller.Command;
import chess.controller.OutputSystem; import chess.controller.event.GameListener;
import chess.model.Color; import chess.model.Color;
import chess.model.Game; import chess.model.Game;
@@ -14,7 +14,7 @@ public class SurrenderCommand extends Command {
} }
@Override @Override
public CommandResult execute(Game game, OutputSystem outputSystem) { public CommandResult execute(Game game, GameListener outputSystem) {
outputSystem.hasSurrendered(player); outputSystem.hasSurrendered(player);
outputSystem.winnerIs(Color.getEnemy(player)); outputSystem.winnerIs(Color.getEnemy(player));
return CommandResult.NotMoved; return CommandResult.NotMoved;

View File

@@ -1,14 +1,14 @@
package chess.controller.commands; package chess.controller.commands;
import chess.controller.Command; import chess.controller.Command;
import chess.controller.OutputSystem;
import chess.controller.PlayerCommand; import chess.controller.PlayerCommand;
import chess.controller.event.GameListener;
import chess.model.Game; import chess.model.Game;
public class UndoCommand extends Command{ public class UndoCommand extends Command{
@Override @Override
public CommandResult execute(Game game, OutputSystem outputSystem) { public CommandResult execute(Game game, GameListener outputSystem) {
PlayerCommand lastAction = game.getLastAction(); PlayerCommand lastAction = game.getLastAction();
if (lastAction == null) if (lastAction == null)
return CommandResult.NotAllowed; return CommandResult.NotAllowed;

View File

@@ -0,0 +1,35 @@
package chess.controller.event;
import chess.model.Color;
import chess.model.Coordinate;
public class GameAdaptator implements GameListener {
@Override
public void playerTurn(Color color) {}
@Override
public void winnerIs(Color color) {}
@Override
public void kingIsInCheck() {}
@Override
public void kingIsInMat() {}
@Override
public void patSituation() {}
@Override
public void hasSurrendered(Color color) {}
@Override
public void gameStarted() {}
@Override
public void promotePawn(Coordinate pieceCoords) {}
@Override
public void updateDisplay() {}
}

View File

@@ -0,0 +1,68 @@
package chess.controller.event;
import java.util.ArrayList;
import java.util.List;
import chess.model.Color;
import chess.model.Coordinate;
public class GameDispatcher implements GameListener{
private final List<GameListener> listeners;
public GameDispatcher() {
this.listeners = new ArrayList<>();
}
public void addListener(GameListener listener) {
this.listeners.add(listener);
}
@Override
public void playerTurn(Color color) {
this.listeners.forEach((l) -> l.playerTurn(color));
}
@Override
public void winnerIs(Color color) {
this.listeners.forEach((l) -> l.winnerIs(color));
}
@Override
public void kingIsInCheck() {
this.listeners.forEach((l) -> l.kingIsInCheck());
}
@Override
public void kingIsInMat() {
this.listeners.forEach((l) -> l.kingIsInMat());
}
@Override
public void patSituation() {
this.listeners.forEach((l) -> l.patSituation());
}
@Override
public void hasSurrendered(Color color) {
this.listeners.forEach((l) -> l.hasSurrendered(color));
}
@Override
public void gameStarted() {
this.listeners.forEach((l) -> l.gameStarted());
}
@Override
public void promotePawn(Coordinate pieceCoords) {
this.listeners.forEach((l) -> l.promotePawn(pieceCoords));
}
@Override
public void updateDisplay() {
this.listeners.forEach((l) -> l.updateDisplay());
}
}

View File

@@ -1,9 +1,9 @@
package chess.controller; package chess.controller.event;
import chess.model.Color; import chess.model.Color;
import chess.model.Coordinate; import chess.model.Coordinate;
public interface OutputSystem { public interface GameListener {
void playerTurn(Color color); void playerTurn(Color color);

View File

@@ -2,11 +2,11 @@ package chess.view.consolerender;
import chess.controller.Command; import chess.controller.Command;
import chess.controller.CommandExecutor; import chess.controller.CommandExecutor;
import chess.controller.OutputSystem;
import chess.controller.commands.GetPieceAtCommand; import chess.controller.commands.GetPieceAtCommand;
import chess.controller.commands.MoveCommand; import chess.controller.commands.MoveCommand;
import chess.controller.commands.PromoteCommand; import chess.controller.commands.PromoteCommand;
import chess.controller.commands.SurrenderCommand; import chess.controller.commands.SurrenderCommand;
import chess.controller.event.GameListener;
import chess.model.Color; import chess.model.Color;
import chess.model.Coordinate; import chess.model.Coordinate;
import chess.model.Move; import chess.model.Move;
@@ -14,7 +14,7 @@ import chess.model.Piece;
import java.util.Scanner; import java.util.Scanner;
public class Console implements OutputSystem { public class Console implements GameListener {
private final Scanner scanner = new Scanner(System.in); private final Scanner scanner = new Scanner(System.in);
private final CommandExecutor commandExecutor; private final CommandExecutor commandExecutor;
private final ConsolePieceName consolePieceName = new ConsolePieceName(); private final ConsolePieceName consolePieceName = new ConsolePieceName();

View File

@@ -19,7 +19,6 @@ import javax.swing.SwingUtilities;
import chess.controller.Command; import chess.controller.Command;
import chess.controller.Command.CommandResult; import chess.controller.Command.CommandResult;
import chess.controller.CommandExecutor; import chess.controller.CommandExecutor;
import chess.controller.OutputSystem;
import chess.controller.commands.CastlingCommand; import chess.controller.commands.CastlingCommand;
import chess.controller.commands.GetAllowedMovesPieceCommand; import chess.controller.commands.GetAllowedMovesPieceCommand;
import chess.controller.commands.GetPieceAtCommand; import chess.controller.commands.GetPieceAtCommand;
@@ -27,12 +26,13 @@ import chess.controller.commands.GetPlayerMovesCommand;
import chess.controller.commands.MoveCommand; import chess.controller.commands.MoveCommand;
import chess.controller.commands.PromoteCommand; import chess.controller.commands.PromoteCommand;
import chess.controller.commands.PromoteCommand.PromoteType; import chess.controller.commands.PromoteCommand.PromoteType;
import chess.controller.event.GameListener;
import chess.controller.commands.UndoCommand; import chess.controller.commands.UndoCommand;
import chess.model.Coordinate; import chess.model.Coordinate;
import chess.model.Move; import chess.model.Move;
import chess.model.Piece; import chess.model.Piece;
public class Window extends JFrame implements OutputSystem { public class Window extends JFrame implements GameListener {
private final CommandExecutor commandExecutor; private final CommandExecutor commandExecutor;