Skip to content

Commit 1f16d1a

Browse files
committed
refactor: 명령어 enum으로 분리 및 옵션 포함된 명령어 객체 추가
1 parent 361883e commit 1f16d1a

File tree

5 files changed

+326
-66
lines changed

5 files changed

+326
-66
lines changed

src/main/java/chess/controller/ChessController.java

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
import chess.controller.dto.BoardDto;
44
import chess.domain.ChessGame;
55
import chess.domain.board.Status;
6-
import chess.domain.command.Command;
6+
import chess.domain.command.CommandOptions;
7+
import chess.domain.command.MoveOptions;
78
import chess.view.InputView;
89
import chess.view.OutputView;
910

11+
import java.util.List;
12+
1013
public class ChessController {
1114

1215
private final InputView inputView;
@@ -18,50 +21,57 @@ public ChessController(final InputView inputView, final OutputView outputView) {
1821
}
1922

2023
public void run() {
21-
outputView.printGuide();
22-
ChessGame chessGame = new ChessGame();
24+
ChessGame chessGame = initialize();
2325

2426
while (chessGame.isRunning()) {
25-
try {
26-
outputView.printTurn(chessGame.isWhiteTurn());
27-
Command command = new Command(inputView.getCommand());
28-
runCommand(chessGame, command);
29-
printBoard(chessGame);
30-
} catch (UnsupportedOperationException e) {
31-
System.out.println(e.getMessage());
32-
}
27+
play(chessGame);
3328
}
3429

35-
printBoard(chessGame);
36-
printStatus(chessGame);
30+
printResult(chessGame);
31+
}
32+
33+
private ChessGame initialize() {
34+
outputView.printGuide();
35+
ChessGame chessGame = new ChessGame();
36+
CommandOptions initialCommandOptions = CommandOptions.of(inputView.getCommand());
37+
executeInitialCommand(initialCommandOptions, chessGame);
38+
39+
return chessGame;
40+
}
41+
42+
private void executeInitialCommand(final CommandOptions commandOptions, final ChessGame chessGame) {
43+
commandOptions.validateInitialCommand();
44+
45+
if (commandOptions.isEnd()) {
46+
chessGame.end();
47+
}
3748
}
3849

39-
private void runCommand(final ChessGame chessGame, final Command command) {
50+
private void play(final ChessGame chessGame) {
4051
try {
41-
if (command.isStart()) {
42-
return;
43-
}
44-
45-
if (command.isEnd()) {
46-
chessGame.end();
47-
return;
48-
}
49-
50-
if (command.isMove()) {
51-
chessGame.move(command.getMoveParameters());
52-
return;
53-
}
54-
55-
if (command.isStatus()) {
56-
printStatus(chessGame);
57-
return;
58-
}
52+
outputView.printTurn(chessGame.isWhiteTurn());
53+
CommandOptions commandOptions = CommandOptions.of(inputView.getCommand());
54+
executeCommand(chessGame, commandOptions);
55+
printBoard(chessGame);
5956
} catch (IllegalArgumentException e) {
6057
System.out.println(e.getMessage());
61-
return;
58+
}
59+
}
60+
61+
private void executeCommand(final ChessGame chessGame, final CommandOptions commandOptions) {
62+
if (commandOptions.isEnd()) {
63+
chessGame.end();
64+
}
65+
66+
if (commandOptions.isMove()) {
67+
List<String> options = commandOptions.getOptions();
68+
MoveOptions moveOptions = new MoveOptions(options);
69+
chessGame.move(moveOptions);
6270
}
6371

64-
throw new UnsupportedOperationException("유효하지 않은 명령어입니다.");
72+
if (commandOptions.isStatus()) {
73+
printStatus(chessGame);
74+
}
6575
}
6676

6777
private void printBoard(final ChessGame chessGame) {
@@ -73,4 +83,9 @@ private void printStatus(final ChessGame chessGame) {
7383
Status status = chessGame.getStatus();
7484
outputView.printStatus(status);
7585
}
86+
87+
private void printResult(final ChessGame chessGame) {
88+
printBoard(chessGame);
89+
printStatus(chessGame);
90+
}
7691
}
Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,58 @@
11
package chess.domain.command;
22

33
import java.util.Arrays;
4-
import java.util.List;
5-
import java.util.stream.Collectors;
4+
import java.util.HashMap;
5+
import java.util.Map;
66

7-
public class Command {
7+
public enum Command {
88

9-
private static final String DELIMITER = " ";
10-
private static final int COMMAND_INDEX = 0;
9+
START("start"),
10+
END("end"),
11+
MOVE("move"),
12+
STATUS("status");
1113

12-
private static final String START = "start";
13-
private static final String END = "end";
14-
private static final String MOVE = "move";
15-
private static final String STATUS = "status";
14+
private static final Map<String, Command> COMMANDS = createCommands();
15+
16+
private static Map<String, Command> createCommands() {
17+
Map<String, Command> commands = new HashMap<>();
18+
19+
Arrays.stream(values())
20+
.forEach(command -> commands.put(command.command, command));
21+
22+
return commands;
23+
}
1624

1725
private final String command;
18-
private final List<String> parameters;
1926

20-
public Command(final String commandLine) {
21-
List<String> chunks = Arrays.stream(commandLine.split(DELIMITER))
22-
.map(String::trim)
23-
.map(String::toLowerCase)
24-
.collect(Collectors.toList());
27+
Command(final String command) {
28+
this.command = command;
29+
}
30+
31+
public static Command of(final String command) {
32+
Command foundCommand = COMMANDS.get(command);
2533

26-
if (chunks.isEmpty()) {
27-
throw new IllegalArgumentException();
34+
if (foundCommand == null) {
35+
throw new IllegalArgumentException("유효하지 않은 명령어입니다.");
2836
}
2937

30-
this.command = chunks.get(COMMAND_INDEX);
31-
this.parameters = chunks.subList(COMMAND_INDEX + 1, chunks.size());
38+
return foundCommand;
3239
}
3340

34-
public boolean isStart() {
35-
return command.equals(START);
41+
public void validateInitialCommand() {
42+
if (isStatus() || isMove()) {
43+
throw new IllegalArgumentException(String.format("%s 또는 %s를 입력해주세요.", START.command, END.command));
44+
}
3645
}
3746

3847
public boolean isEnd() {
39-
return command.equals(END);
48+
return this.equals(END);
4049
}
4150

4251
public boolean isMove() {
43-
return command.equals(MOVE);
52+
return this.equals(MOVE);
4453
}
4554

4655
public boolean isStatus() {
47-
return command.equals(STATUS);
48-
}
49-
50-
public MoveParameters getMoveParameters() {
51-
if (parameters.size() != 2) {
52-
throw new IllegalArgumentException();
53-
}
54-
55-
return new MoveParameters(parameters);
56+
return this.equals(STATUS);
5657
}
5758
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package chess.domain.command;
2+
3+
import java.util.Arrays;
4+
import java.util.Collections;
5+
import java.util.List;
6+
import java.util.stream.Collectors;
7+
8+
public class CommandOptions {
9+
10+
private static final String DELIMITER = " ";
11+
private static final int COMMAND_INDEX = 0;
12+
private static final int CHECK_VALUE_IF_COMMAND_HAS_OPTIONS = 1;
13+
private static final int FIRST_OPTION_INDEX = 1;
14+
15+
private final Command command;
16+
private final List<String> options;
17+
18+
private CommandOptions(final Command command, final List<String> options) {
19+
this.command = command;
20+
this.options = options;
21+
}
22+
23+
public static CommandOptions of(final String text) {
24+
validateEmpty(text);
25+
List<String> commandAndOptions = split(text);
26+
Command command = Command.of(commandAndOptions.get(COMMAND_INDEX));
27+
List<String> options = extractOptions(commandAndOptions);
28+
System.out.println(options.size());
29+
30+
return new CommandOptions(command, options);
31+
}
32+
33+
private static void validateEmpty(final String text) {
34+
if (text == null) {
35+
throw new IllegalArgumentException("명령어가 존재하지 않습니다.");
36+
}
37+
}
38+
39+
private static List<String> split(final String text) {
40+
return Arrays.stream(text.split(DELIMITER))
41+
.map(String::trim)
42+
.map(String::toLowerCase)
43+
.collect(Collectors.toList());
44+
}
45+
46+
private static List<String> extractOptions(final List<String> commandAndOptions) {
47+
if (hasOptions(commandAndOptions)) {
48+
return commandAndOptions.subList(FIRST_OPTION_INDEX, commandAndOptions.size());
49+
}
50+
51+
return Collections.emptyList();
52+
}
53+
54+
private static boolean hasOptions(final List<String> splitText) {
55+
return splitText.size() > CHECK_VALUE_IF_COMMAND_HAS_OPTIONS;
56+
}
57+
58+
public void validateInitialCommand() {
59+
command.validateInitialCommand();
60+
}
61+
62+
public boolean isEnd() {
63+
return command.isEnd();
64+
}
65+
66+
public boolean isMove() {
67+
return command.isMove();
68+
}
69+
70+
public boolean isStatus() {
71+
return command.isStatus();
72+
}
73+
74+
public List<String> getOptions() {
75+
return Collections.unmodifiableList(options);
76+
}
77+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package chess.domain.command;
2+
3+
import org.junit.jupiter.api.DisplayName;
4+
import org.junit.jupiter.params.ParameterizedTest;
5+
import org.junit.jupiter.params.provider.CsvSource;
6+
import org.junit.jupiter.params.provider.NullSource;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
10+
11+
class CommandOptionsTest {
12+
13+
@ParameterizedTest
14+
@CsvSource(value = {"start, 0", "end, 0", "move b2 b3, 2", "status, 0"})
15+
@DisplayName("옵션이 담긴 명령어를 반환한다.")
16+
void of(String text, int expected) {
17+
//when
18+
CommandOptions commandOptions = CommandOptions.of(text);
19+
System.out.println(commandOptions.getOptions().size());
20+
21+
//then
22+
assertThat(commandOptions.getOptions()).hasSize(expected);
23+
}
24+
25+
@ParameterizedTest
26+
@NullSource
27+
@DisplayName("명령어가 null일 경우 예외가 발생한다.")
28+
void of_fail(String text) {
29+
//when //then
30+
assertThatThrownBy(() -> CommandOptions.of(text))
31+
.isInstanceOf(IllegalArgumentException.class)
32+
.hasMessage("명령어가 존재하지 않습니다.");
33+
}
34+
35+
@ParameterizedTest
36+
@CsvSource(value = {"status, move"})
37+
@DisplayName("시작 또는 종료 명령어가 아닐 경우 예외가 발생한다.")
38+
void validateInitialCommand(String text) {
39+
//given
40+
CommandOptions commandOptions = CommandOptions.of(text);
41+
42+
//when // then
43+
assertThatThrownBy(commandOptions::validateInitialCommand)
44+
.isInstanceOf(IllegalArgumentException.class)
45+
.hasMessage("start 또는 end를 입력해주세요.");
46+
}
47+
48+
@ParameterizedTest
49+
@CsvSource(value = {"start, false", "end, true", "move, false", "status, false"})
50+
@DisplayName("종료 명령어인지 확인한다.")
51+
void isEnd(String text, boolean expected) {
52+
//given
53+
CommandOptions commandOptions = CommandOptions.of(text);
54+
55+
//when
56+
boolean actual = commandOptions.isEnd();
57+
58+
//then
59+
assertThat(actual).isEqualTo(expected);
60+
}
61+
62+
@ParameterizedTest
63+
@CsvSource(value = {"start, false", "end, false", "move, true", "status, false"})
64+
@DisplayName("종료 명령어인지 확인한다.")
65+
void isMove(String text, boolean expected) {
66+
//given
67+
CommandOptions commandOptions = CommandOptions.of(text);
68+
69+
//when
70+
boolean actual = commandOptions.isMove();
71+
72+
//then
73+
assertThat(actual).isEqualTo(expected);
74+
}
75+
76+
@ParameterizedTest
77+
@CsvSource(value = {"start, false", "end, false", "move, false", "status, true"})
78+
@DisplayName("종료 명령어인지 확인한다.")
79+
void isStatus(String text, boolean expected) {
80+
//given
81+
CommandOptions commandOptions = CommandOptions.of(text);
82+
83+
//when
84+
boolean actual = commandOptions.isStatus();
85+
86+
//then
87+
assertThat(actual).isEqualTo(expected);
88+
}
89+
}

0 commit comments

Comments
 (0)