wonslee / object-study

📔오브젝트 예제 코드를 따라 공부, 토론하는 스터디 그룹
0 stars 1 forks source link

4장 공부 내용 #18

Open wonslee opened 6 months ago

wonslee commented 6 months ago

배운 내용

https://zorbathegeek.tistory.com/66

적용

java-baseball 코드를 리팩토링했습니다.

플레이어의 게임 진행 결정 객체 캡슐화

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;
    }

문제점 :

리팩토링 후 :

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());
    }
    // ...
}

개선점 :

야구공 집합의 자율성 증가

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;
    }