Java Enum 활용기 참고하여 작성되었습니다.

자바 이넘

자비 enum 을 활용하면 상태와 행위를 한곳에서 관리할 수 있는 장점에 대해서 알아 보겠습니다.

예시로 로또 상금 로직 구현해보면서 파악해보겠습니다. 우선 Enum 미적용된 코드부터 살펴 보겠습니다.

Enum 으로 적용안되었을 경우


class LottoRank {
    private final static Long FIRST_PRIZE = 1000000L;
    private final static Long SECOND_PRIZE = 80000L;
    private final static Long THIRD_PRIZE = 5000L;
    private final static Long NONE_PRIZE = 0L;

    private final static int MATCHED_COUNT_FIRST = 6;
    private final static int MATCHED_COUNT_SECOND = 5;
    private final static int MATCHED_COUNT_THIRD = 4;

    public Long getPrize(int matchedCount) {
        switch (matchedCount) {
            case  MATCHED_COUNT_FIRST :
                return FIRST_PRIZE;
            case  MATCHED_COUNT_SECOND :
                return SECOND_PRIZE;
            case  MATCHED_COUNT_THIRD :
                return THIRD_PRIZE;
        }
        return 0L;
    }
}

LottoRank 클래스는 맞춘 로또 숫자에 따라 상금을 반환해주는 getPrize 메소드를 가지고 있습니다.

# 테스트 코드
LottoRank lottoRank = new LottoRank();

int matchedCount = 6;

Long prize = lottoRank.getPrize(matchedCount);
System.out.println(prize);  // 6개 일치이므로 1000000 이 출력됩니다.

우선 위 코드는 확장성에 취약한 상태입니다.
만약에 4등의 상금이 줘야하는 추가 요구상황이 주어졌다면 어떻게 될까요?

...
    # 추가
    private final static Long FOURTH_PRIZE = 1000L;

...
    public Long getPrize(int matchedCount) {
        switch (matchedCount) {
            case  MATCHED_COUNT_FIRST :
                return FIRST_PRIZE;
            case  MATCHED_COUNT_SECOND :
                return SECOND_PRIZE;
            case  MATCHED_COUNT_THIRD :
                return THIRD_PRIZE;
             # 추가
            case  MATCHED_COUNT_FOURTH :
                return FOURTH_PRIZE;
        }
        return 0L;
    }

이처럼 상태와 로직을 각각 수정해주어야 합니다.
LottoRank 클래스의 인스턴스 변수와 메소드가 같이 있어서 그나마 나아보일 수도 있지만,
위 예제는 단순한 예제이고 복잡해질 경우 유지보수와 확장성에서 어려움을 격을 수 있습니다.

Enum 을 활용한다면 어떻게 될까요?


enum LottoRankEnum {
    FIRST(6, 1_000_000L),
    SECOND(5, 80_000L),
    THIRD(4, 5_000L),
    FOURTH_PRIZE(3, 1_000L),
    NONE(0, 0L);

    public int matchedCount; // 당첨된 로또 갯수
    public long prize; // 상금

    LottoRankEnum(int matchedCount, Long prize) {
        this.matchedCount = matchedCount;
        this.prize = prize;
    }

    public static LottoRankEnum valueOf(int matchedCount) {
        return Arrays.stream(values())
            .filter(lottoRankEnum -> lottoRankEnum.matchedCount == matchedCount)
            .findFirst().orElse(NONE);

    }
}

테스트 코드

@Test
void LottoRankEnumTest() {
    LottoRankEnum lottoRankEnum = LottoRankEnum.valueOf(6);
    System.out.println(lottoRankEnum.prize); // 출력 : 1000000
}

위 Enum 에도 4등이 빠져 있습니다. 4등을 추가 해주고 싶다면

  FOURTH_PRIZE(3, 1_000L),

위 코드만 추가해주면 확장 할 수 있습니다. 이는 상태와 로직이 하나로 정의 되어 있으므로 한번에 관리될수 있는 장점이 있습니다.

또한 처음 클래스로 만들었던 코드에서는 FIRST_PRIZE = 1000000L, MATCHED_COUNT_FIRST = 6 연관이 있지만, 서로의 연관성은 로직을 보지 않는다면 알기가 힘듭니다. 이는 프로젝트가 커지면 실수로 이어질수 있는부분이라고 생각됩니다.

Enum 객체에서는 FIRST(6, 1_000_000L) 이처럼 두 상태가 같이 움직이게 되므로 연관이 있다는걸 바로 알수있습니다.
또한, 상태와 로직이 같이 움직이므로 확장성과 유지,보수에서 많은 장점이 있어보입니다.