[모던 자바 인 액션] chap02. 동적 파라미터화 코드 전달하기
2023. 2. 18. 18:00ㆍJava
동적 파라미터화란? - 아직은 어떻게 실행할 것인지 결정하지 않은 코드 블록
예제 코드
public static List<Apple> filterGreenApples(List<Apple> inventory) {
List<Apple> result = new ArrayList<>();
for(Apple apple : inventory) {
if(GREEN.equals(apple.getColor()))
result.add(apple);
}
return result;
}
인터페이스를 구현하는 객체들로 동작파라미터화를 시키면 메서드가 다양한 동작을 받아 내부적으로 다양한 동작을 수행할 수 있다.
색을 파라미터화
public static List<Apple> filterApplesByColor(List<Apple> inventory, Color color) {
List<Apple> result = new ArrayList<>();
for(Apple apple : inventory) {
if(apple.getColor().equals(color))
result.add(apple);
}
return result;
}
메서드에 파라미터를 추가하면 좀 더 유연하게 요구사항을 대처할 수 있다.
모든걸 파라미터화 하다 보면..
public static List<Apple> filterApples(List<Apple> inventory, Color color,
int weight, boolean flag) {
List<Apple> result = new ArrayList<>();
for(Apple apple : inventory) {
if((flag && apple.getColor().equals(color)) ||
!flag && apple.getWeight() > weight)
result.add(apple);
}
return result;
}
누가 봐도 보자마자 알아보기 힘든 코드다. flag가 정확히 뭘 요구하는지를 for문의 순서를 따라가야 하는 괴상한 코드가 되어버렸다. 계속 요구사항이 바뀔때마다 이런식으로 파라미터화 시킨다면 여간 난처한 상황이 아닐것이다.
인터페이스로 조건을 만든다면
public interface ApplePredicate {
boolean test(Apple apple);
}
public class AppleHeavyWeightPredicate implements ApplePredicate {
@Override
public boolean test(Apple apple) {
return apple.getWeight() > 150;
}
}
public class AppleGreenColorPredicate implements ApplePredicate {
@Override
public boolean test(Apple apple) {
return GREEN.equals(apple.getColor());
}
}
public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {
List<Apple> result = new ArrayList<>();
for(Apple apple : inventory) {
if(p.test(apple))
result.add(apple);
}
return result;
}
코드 중복에 전략패턴을 쓰는 방법도 나름의 방법이지만, 동적 파라미터화된 코드가 많아진다면 interface를 상속하는 코드마다 구현하는 것도 귀찮아질 수 있다. 이렇게 인스터스화 될 코드를 만드는 방법보다 인스터스화와 동시에 코드 구현을 수행할 수 있도록 익명 클래스를 제공한다. 하지만 익명 클래스가 모든 귀찮음과 어려움을 해결하는 것은 아니다.
익명 클래스란? - 자바의 지역 클래스와 비슷한 개념이다. 말 그대로 이름이 없는 클래스다. 익명 클래스를 이용하면 클래스 선언과 인스턴스화를 동시에 할 수 있다. 즉석에서 필요한 구현을 만들어서 사용할 수 있다.
익명 클래스가 가질 수 있는 문제
- 익명 클래스는 많은 공간을 차지한다. (코드를 장황하게 만든다)
- 많은 프로그래머가 익명 클래스의 사용에 익숙치 않다.
apples = filterApples(apples, new ApplePredicate() {
@Override
public boolean test(Apple apple) {
return apple.getColor().equals(Color.RED);
}
});
// 익명 클래스를 람다로 바꾼다
apples = filterApples(apples, apple -> apple.getColor().equals(Color.RED));
코드 추상화
public static <T> List<T> filter(List<T> list, Predicate<T> p) {
List<T> result = new ArrayList<>();
for(T e : list) {
if(p.test(e)) {
result.add(e);
}
}
return result;
}
List<Apple> redApples =
filter(inventory, (Apple apple) -> Color.RED.equals(apple.getColor()));
List<Integer> evenNumbers =
filter(numbers, (Integer num) -> num%2 == 0);
// T로 추상화 시킬수도 있다.
'Java' 카테고리의 다른 글
[모던 자바 인 액션] chap05. 스트림 활용 (0) | 2023.03.05 |
---|---|
[모던 자바 인 액션] chap04. 스트림이란? (0) | 2023.03.01 |
[모던 자바 인 액션] chap03. 람다 표현식(2) (0) | 2023.02.24 |
[모던 자바 인 액션] chap03. 람다 표현식(1) (0) | 2023.02.21 |
[모던 자바 인 액션] chap01. 자바 8에 무슨 일이..? (0) | 2023.02.13 |