페어 프로그래밍을 하면서 어떻게 등수를 결정할 지 고민을 했었다. 결론부터 말하면 정답갯수와 보너스넘버를 갖고있는지 두 매개변수를 전달하는 메서드를 만들고, 만약 정답갯수가 5개일 때 보너스넘버를 이용해서 2등과 3등을 구분하는 메서드를 이용했었다. 이렇게 구현하면 아래왜 같이 두가지 메서드가 필요하다.
public static LottoRank valueOf(int sameCount, boolean bonus) {
if (sameCount == 5) {
checkSecondOrThird(bonus);
}
return Arrays.stream(values())
.filter(lottoRank -> lottoRank.getCorrectNumber() == sameCount)
.findFirst()
.orElseThrow(IllegalArgumentException::new);
}
private static LottoRank checkSecondOrThird(boolean bonus) {
if (bonus) {
return SECOND;
}
return THIRD;
}
구현하면서도 뭔가 복잡하고 메서드를 두개 쓰는게 마음에 안들었는데, 이번에 네오가 강의를 하면서 BiPredicate에 대해서 알려주면서 깔끔하게 구현할 수 있는 방법을 배웠다.
test()
메서드를 이용하면 boolean 값을 반환해준다.public enum LottoRank {
NOTHING(0, 0, (correctNumber, matchBonus) -> correctNumber < 3),
FIFTH(3, 5000, (correctNumber, matchBonus) -> correctNumber == 3),
FOURTH(4, 50000, (correctNumber, matchBonus) -> correctNumber == 4),
THIRD(5, 1500000, (correctNumber, matchBonus) -> correctNumber == 5 && !matchBonus),
SECOND(5, 30000000, (correctNumber, matchBonus) -> correctNumber == 5 && matchBonus),
FIRST(6, 2000000000, (correctNumber, matchBonus) -> correctNumber == 6);
private final int correctNumber;
private final int prizeAmount;
private final BiPredicate<Integer, Boolean> isMatch;
...
public static LottoRank valueOf(int sameCount, boolean bonus) {
return Arrays.stream(values())
.filter(lottoRank -> lottoRank.isMatch.test(sameCount, bonus))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("[ERROR] 조건에 맞지 않는 당첨입니다."));
}
Enum에 BiPredicate 값을 추가하고 valueOf()
를 호출할 때 BiPredicate를 통해서 확인할 수 있게된다. 위에 메서드를 두개로 분리했었는데 이를 하나로 통합할 수 있다. 그리고 enum의 상수에 조건이 같이 명시되어 당첨조건을 한눈에 볼 수 있어서 더 좋은 것 같다.
BiPredicate는 argument 두개를 받아 boolean으로 반환하는 함수형 인터페이스이다.
함수형 인터페이스도 나중에 공부해보고 단순히 기능을 쓰는 것이 아니라, 스트림과 람다식을 이해하고나서 애용할 것 같다!
https://docs.oracle.com/javase/8/docs/api/java/util/function/BiPredicate.html