Java 공부 46일차(열거형 - ENUM이란?)3편

임선구·2025년 3월 28일

몸 비틀며 Java

목록 보기
47/58

오늘의 잔디


오늘의 공부


열거형 - 리팩토링2

이제 열거형을 사용해보자.
열거형도 클래스이다. 앞서 했던 리팩토링을 열거형인 Grade 에 동일하게 적용해보자.

package enumeration.ref2;
public enum Grade {
 BASIC(10), GOLD(20), DIAMOND(30);
 private final int discountPercent;
 Grade(int discountPercent) {
 this.discountPercent = discountPercent;
 }
 public int getDiscountPercent() {
 return discountPercent;
 }
}
  • discountPercent 필드를 추가하고, 생성자를 통해서 필드에 값을 저장한다.
  • 열거형은 상수로 지정하는 것 외에 일반적인 방법으로 생성이 불가능하다. 따라서 생성자에 접근제어자를 선언할
    수 없게 막혀있다. private 이라고 생각하면 된다.
  • BASIC(10) 과 같이 상수 마지막에 괄호를 열고 생성자에 맞는 인수를 전달하면 적절한 생성자가 호출된다.
  • 값을 조회하기 위해 getDiscountPercent() 메서드를 추가했다. 열거형도 클래스이므로 메서드를 추가할 수 있다.
package enumeration.ref2;
public class DiscountService {
 public int discount(Grade grade, int price) {
 return price * grade.getDiscountPercent() / 100;
 }
}
  • 기존에 있던 if 문이 완전히 제거되고, 단순한 할인율 계산 로직만 남았다.
package enumeration.ref2;public class EnumRefMain2 {
 public static void main(String[] args) {
 int price = 10000;
 DiscountService discountService = new DiscountService();
 int basic = discountService.discount(Grade.BASIC, price);
 int gold = discountService.discount(Grade.GOLD, price);
 int diamond = discountService.discount(Grade.DIAMOND, price);
 System.out.println("BASIC 등급의 할인 금액: " + basic);
 System.out.println("GOLD 등급의 할인 금액: " + gold);
 System.out.println("DIAMOND 등급의 할인 금액: " + diamond);
 }
}

실행 결과

BASIC 등급의 할인 금액: 1000
GOLD 등급의 할인 금액: 2000
DIAMOND 등급의 할인 금액: 3000

실행 결과는 기존과 같다.

열거형 - 리팩토링3

다음 코드를 리팩토링 하고 나니, 단순한 할인율 계산만 남았다.

public class DiscountService {
 public int discount(Grade grade, int price) {
 return price * grade.getDiscountPercent() / 100;
 }
}
  • 이 코드를 보면 할인율 계산을 위해 Grade 가 가지고 있는 데이터인 discountPercent 의 값을 꺼내서 사용한다.
  • 결국 Grade 의 데이터인 discountPercent 를 할인율 계산에 사용한다.
  • 객체지향 관점에서 이렇게 자신의 데이터를 외부에 노출하는 것 보다는, Grade 클래스가 자신의 할인율을 어떻게 계산하는지 스스로 관리하는 것이 캡슐화 원칙에 더 맞다.

Grade 클래스 안으로 discount() 메서드를 이동시키자.
일부 코드 수정이 필요하다.

package enumeration.ref3;
public enum Grade {
 BASIC(10), GOLD(20), DIAMOND(30);
 private final int discountPercent;
 Grade(int discountPercent) {
 this.discountPercent = discountPercent;
 }
 public int getDiscountPercent() {
 return discountPercent;
 }
 //추가
 public int discount(int price) {
 return price * discountPercent / 100;
 }
}
  • Grade 내부에 discount() 메서드를 만들어서, 이제 할인율을 스스로 계산한다.
package enumeration.ref3;
public class DiscountService {
 public int discount(Grade grade, int price) {
 return grade.discount(price);
 }
}
  • 할인율 계산은 이제 Grade 가 스스로 처리한다. 따라서 DiscountService.discount() 메서드는 단순히Grade.discount() 를 호출하기만 하면 된다.
package enumeration.ref3;
public class EnumRefMain3_1 {
 public static void main(String[] args) {
 int price = 10000;
 DiscountService discountService = new DiscountService();
 int basic = discountService.discount(Grade.BASIC, price);
 int gold = discountService.discount(Grade.GOLD, price);
 int diamond = discountService.discount(Grade.DIAMOND, price);
 System.out.println("BASIC 등급의 할인 금액: " + basic);
 System.out.println("GOLD 등급의 할인 금액: " + gold);
 System.out.println("DIAMOND 등급의 할인 금액: " + diamond);
 }
}

실행 결과

BASIC 등급의 할인 금액: 1000
GOLD 등급의 할인 금액: 2000
DIAMOND 등급의 할인 금액: 3000

실행 결과는 기존과 같다.

DiscountService 제거

Grade 가 스스로 할인율을 계산하면서 DiscountService 클래스가 더는 필요하지 않게 되었다.

package enumeration.ref3;
public class EnumRefMain3_2 {
 public static void main(String[] args) {
 int price = 10000;
 System.out.println("BASIC 등급의 할인 금액: " +
Grade.BASIC.discount(price)); System.out.println("GOLD 등급의 할인 금액: " +
Grade.GOLD.discount(price));
 System.out.println("DIAMOND 등급의 할인 금액: " +
Grade.DIAMOND.discount(price));
 }
}

실행 결과

BASIC 등급의 할인 금액: 1000
GOLD 등급의 할인 금액: 2000
DIAMOND 등급의 할인 금액: 3000
  • 각각의 등급별로 자신의 discount() 를 직접 호출하면 할인율을 구할 수 있다.
  • DiscountService 를 제거해도 되지만, 앞의 예제에서 사용되므로 복습을 위해 남겨두자.

중복 제거

출력 부분의 중복을 제거하자.

package enumeration.ref3;
public class EnumRefMain3_3 {
 public static void main(String[] args) {
 int price = 10000;
 printDiscount(Grade.BASIC, price);
 printDiscount(Grade.GOLD, price);
 printDiscount(Grade.DIAMOND, price);
 }
 private static void printDiscount(Grade grade, int price) {
 System.out.println(grade.name() + " 등급의 할인 금액: " +
grade.discount(price));
 }
}

실행 결과

BASIC 등급의 할인 금액: 1000
GOLD 등급의 할인 금액: 2000
DIAMOND 등급의 할인 금액: 3000

grade.name() 을 통해서 ENUM의 상수 이름을 사용할 수 있다.

ENUM 목록

이후에 새로운 등급이 추가되더라도 main() 코드의 변경 없이 모든 등급의 할인을 출력해보자.

package enumeration.ref3;
public class EnumRefMain3_4 {
 public static void main(String[] args) {
 int price = 10000;
 Grade[] grades = Grade.values();
 for (Grade grade : grades) {
 printDiscount(grade, price);
 }
 }
 private static void printDiscount(Grade grade, int price) {
 System.out.println(grade.name() + " 등급의 할인 금액: " +
grade.discount(price));
 }
}

실행 결과

BASIC 등급의 할인 금액: 1000
GOLD 등급의 할인 금액: 2000
DIAMOND 등급의 할인 금액: 3000

Grade.values() 를 사용하면 Grade 열거형의 모든 상수를 배열로 구할 수 있다.

profile
끝까지 가면 내가 다 이겨

0개의 댓글