GameManager : 게임을 진행시키는 역할. 플레이어의 게임 진행 결정을 입력받아 상태로써 가지는 책임과 게임을 생성하고 진행하는 책임이 있습니다.
PlayerDecision : 게임 진행 여부(시작, 종료)에 대한 판단 책임이 있으며 게임 진행 신호(1 혹은 2)라는 상태를 가집니다. ENUM 객체입니다.
public class Application {
public static void main(String[] args) {
GameManager gameManager = new GameManager();
gameManager.manage();
}
}
public class GameManager {
private PlayerDecision playerDecision;
// ...
private boolean isPlayerDecisionRestart() {
return this.playerDecision.sign == PlayerDecision.RESTART.sign;
}
문제점 :
기존에 판단 책임을 PlayerDecision이 지고 있지 않아서 OCP를 위반하게 됩니다. 만약 게임 진행 여부에 대한 신호가 추가되거나 바뀔 때 GameManager 객체에도 변경 영향이 미치게 됩니다.
캡슐화를 하지 않아 결합도가 높아진 상태입니다.
리팩토링 후 :
public enum PlayerDecision {
RESTART(1), FINISH(2);
private final int sign;
public static final String DECISION_GUIDE = "게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.";
public static final String INVALID_DECISION_MESSAGE = "해당 입력은 1 또는 2만 가능합니다.";
PlayerDecision(int sign) {
this.sign = sign;
}
public boolean isKeepPlaying() {
return this.equals(RESTART);
}
public static PlayerDecision of(int intParameter) {
return switch (intParameter) {
case 1 -> RESTART;
case 2 -> FINISH;
default -> throw new IllegalArgumentException(INVALID_DECISION_MESSAGE);
};
}
public class GameManager {
private PlayerDecision playerDecision;
public void manage() {
do {
Game game = new Game();
game.run();
resolvePlayerDecisionFromInput();
} while (playerDecision.isKeepPlaying());
}
// ...
}
개선점 :
OCP 문제가 해결되었습니다. 게임 진행 여부에 대한 기준이 변경 혹은 추가되어도 GameManager은 영향 받지 않습니다.
야구공 집합의 자율성 증가
Inning : 한 이닝의 결과를 계산하고 판정하는 역할.
결과를 계산하고 판정하는 책임을 가집니다.
Pitch : 한쪽 플레이어의 야구공 3자리 집합.
야구공들에 대한 검증, 상대방과의 스트라이크 카운트 및 볼 카운트 비교 책임을 가집니다.
/**
* Inning : 한 이닝의 결과를 계산하고 판정하는 역할. 의존성: BaseBallMount, Sign
*/
public class Inning {
// ...
public String referee() {
calculateResult(computerPitch, playerPitch);
return judgeMountResult();
}
// Pitch의 자율성 낮은 상태
private void calculateResult(Pitch computerPitch, Pitch playerPitch) {
List<BaseBall> computerBaseBalls = computerPitch.getBaseBalls();
List<BaseBall> playerBaseBalls = playerPitch.getBaseBalls();
for (int i = 0; i < playerBaseBalls.size(); i++) {
if (computerBaseBalls.get(i).equals(playerBaseBalls.get(i))) {
this.strikeCount++;
} else if (computerBaseBalls.contains(playerBaseBalls.get(i))) {
this.ballCount++;
}
}
}
public class Pitch {
// ...
private final List<BaseBall> baseBallList;
// 퍼블릭 인터페이스를 통해 필드가 노출된 상태
public List<BaseBall> getBaseBallList() {
return baseBallList;
}
}
리팩토링 후 :
List 필드의 무분별한 접근자를 제거, 캡슐화했습니다.
또한 스트라이크 카운팅과 볼 카운팅의 책임을 Pitch로 이동했습니다.
public class Pitch {
//...
public int calculateStrikeCount(Pitch otherPitch) {
int count = 0;
for (int i = 0; i < baseBallList.size(); i++) {
if (baseBallList.get(i).equals(otherPitch.baseBallList.get(i))) {
count++;
}
}
return count;
}
public int calculateBallCount(Pitch otherPitch) {
int count = 0;
for (int i = 0; i < baseBallList.size(); i++) {
if (baseBallList.contains(otherPitch.baseBallList.get(i))) {
count++;
}
}
return count;
}
배운 내용
https://zorbathegeek.tistory.com/66
적용
java-baseball 코드를 리팩토링했습니다.
플레이어의 게임 진행 결정 객체 캡슐화
GameManager
: 게임을 진행시키는 역할. 플레이어의 게임 진행 결정을 입력받아 상태로써 가지는 책임과 게임을 생성하고 진행하는 책임이 있습니다.PlayerDecision
: 게임 진행 여부(시작, 종료)에 대한 판단 책임이 있으며 게임 진행 신호(1 혹은 2)라는 상태를 가집니다. ENUM 객체입니다.문제점 :
PlayerDecision
이 지고 있지 않아서 OCP를 위반하게 됩니다. 만약 게임 진행 여부에 대한 신호가 추가되거나 바뀔 때 GameManager 객체에도 변경 영향이 미치게 됩니다.리팩토링 후 :
개선점 :
GameManager
은 영향 받지 않습니다.야구공 집합의 자율성 증가
Inning
: 한 이닝의 결과를 계산하고 판정하는 역할.결과를 계산하고 판정하는 책임을 가집니다.
Pitch
: 한쪽 플레이어의 야구공 3자리 집합.야구공들에 대한 검증, 상대방과의 스트라이크 카운트 및 볼 카운트 비교 책임을 가집니다.
리팩토링 후 :
List 필드의 무분별한 접근자를 제거, 캡슐화했습니다.
또한 스트라이크 카운팅과 볼 카운팅의 책임을 Pitch로 이동했습니다.