다음과 같은 요구사항이 있다.
로그인 사용자의 경우 연령별 요금으로 계산
- 청소년: 운임에서 350원을 공제한 금액의 20%할인
- 어린이: 운임에서 350원을 공제한 금액의 50%할인
- 청소년: 13세 이상~19세 미만
- 어린이: 6세 이상~ 13세 미만
이 또한 if-else를 통해 사용자가 청소년인지, 어린이인지, 혹은 그에 해당하지 않는 지 확인한 뒤 그에 알맞은 요금을 계산해서 리턴할 수 있다.
하지만, 이번에는 Enum을 이용해 처리해보자.
사실 Enum을 사용하는 이유는 Enum의 필드로서 함수형 인터페이스를 받은 뒤, 그에 알맞은 Enum Type을 갖도록 함으로서 분기문을 다룰 수 있기 때문이다.
먼저 코드로 보자면 다음과 같다.
public enum AgePolicy {
TWENTIES(age -> age > 19, 0, 0),
TEENAGERS(age -> 13 <= age && age < 19, 350, 0.2),
PRESCHOOLER(age -> 6 <= age && age < 13, 350, 0.5),
BABIES(age -> age < 6, 0, 1);
private final IntPredicate agePredicate;
private final int deductionFare;
private final double discountRate;
AgePolicy(IntPredicate agePredicate, int deductionFare, double discountRate) {
this.agePredicate = agePredicate;
this.deductionFare = deductionFare;
this.discountRate = discountRate;
}
public static AgePolicy of(int age) {
return Arrays.stream(AgePolicy.values())
.filter(agePolicy -> agePolicy.agePredicate.test(age))
.findAny()
.orElseThrow(() -> new IllegalArgumentException("해당하는 나이가 존재하지 않습니다."));
}
public int calculateFareAppliedAgePolicy(int currentFare) {
return (int) ((currentFare - deductionFare) * (1 - discountRate));
}
}
분기문을 통해 이 사용자가 청소년인지, 어린이인지 구분할 것을 Enum의 values를 활용하여 모든 enum을 돌면서 첫번째 인자인 Inpredicate에 알맞은 age인지 확인하고, 그에 알맞은 Enum 객체를 리턴한다.
사실, 이 방법이 분기문을 개선했는지에 대해서는 잘 모르겠다.
단순히 두 개의 for-loop를 stream을 이용해 한줄로 작성하듯이, 이 또한 반복되는 if-else문을 함수형 인터페이스를 이용해 줄였지 "개선"은 아닌 것 같다는 생각이 들기도 한다.
아무튼 위와 같은 방식으로 if-else를 클래스 내부에서 처리할 수 있다.
(이 내용은 함수형 인터페이스에 대해 공부한 뒤 조금 더 보완하겠다.)
끗