[모던 자바 인 액션] Ch.2 - 동작 파라미터화
해당 서적을 참고하여 개인 공부용으로 정리한 글입니다.
기본적인 Java 지식이 있으시다면 이해하기 수월한 정도입니다 :)
또한, 해당 책은 2018년 Java 11 기준으로 작성되어 있습니다.
따라서 이후 버전에서 변경된 내용은 수정하여 작성했습니다. (아는 부분만 말입니다..)
1. 동작 파라미터화
시시각각 변화하는 사용자 요구사항에 대응하기 위해 동작 파라미터화를 한다.
동작 파라미터화 : 어떻게 실행할 것인지 결정하지 않은 코드 블록
이 코드 블록은 나중에 프로그램에서 호출한다. 즉, 실행이 나중으로 미뤄진다.
기존에는 동작 파리미터화를 추가하려면 불필요한 코드가 늘어났지만, 자바 8에서는 람다식으로 해결했다.
필터링의 속성들을 전부 파라미터에 추가하면 초반 2~3개는 그럭저럭 견딜만 하지만, 그 이후부터는 답이 없다.
크기, 무게, 색상, 출하지 등등.. 파라미터 개수가 많아지면 하나하나 다 만들어줘야 할 것이다.
따라서, 공통 동작을 중심으로 하나의 메서드로 만들고 조건을 파라미터화 한다.
Predicate를 통해 선택 조건을 결정하는 인터페이스를 정의하고
이를 구현한 클래스들을 통해 전략 패턴(Stratrgy Pattern)을 만들 수 있다.
이 방법 역시 코드를 전달하는 동작 파라미터화이지만, 메서드를 구현하는 객체를 감싸야하고, 클래스를 모두 정의해줘야 한다.
컬렉션 탐색 로직과 각 항목에 적용할 동작을 분리할 수 있다는 것이 동작 파라미터화의 강점이다.
public static void prettyPrintApple(List<Apple> inventory, ApplePredicate p) {
for (Apple apple : inventory) {
String output = p.print(apple);
System.out.println(output);
}
}
public interface ApplePredicate {
String print(Apple apple);
}
public class FirstApplePredicate implements ApplePredicate {
public String print(Apple apple) {
return "PERFECT APPLE : " + apple.getType();
}
}
...many things
prettyPrintApple(inventory, new FirstApplePredicate());
이처럼 여러 클래스를 정의하고 인스턴스화하는 것은 상당히 번거로운 작업이다.
2. 복잡한 과정 간소화
우선 클래스의 선언과 인스턴스화를 동시에 수행할 수 있는 익명 클래스를 활용해 해결해본다.
List<Apple> redApples = filterApples(inventory, new ApplePredicate() {
public boolean test(Apple apple) {
return RED.equals(apple.getColor());
}
});
하지만 여전히 로직과 상관없는 코드들이 많다.
또한 코드를 전달하는 과정에서 결국 객체를 만들고 명시적으로 새로운 동작을 정의하는 메서드를 구현해야 한다는 점은 변하지 않는다.
람다식을 이용하면 다음처럼 재구현할 수 있다.
List<Apple> redApples = filterApples(inventory, apple -> RED.equals(apple.getColor()));
이제는 사과뿐만 아니라 바나나, 오렌지 등에 대해서도 필터 메서드를 사용할 수 있도록 추상화한다.
//Predicate는 Java 표준 라이브러리다.
public interface Predicate<T> {
boolean test(T t);
}
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 -> RED.equals(apple.getColor()));
List<Apple> yellowBananas = filter(inventory, banana -> YELLOW.equals(banana.getColor()));
결론
- 메서드 내부적으로 다양한 동작을 수행할 수 있도록 동작 파라미터화한다.
- 람다식을 이용한 동작 파라미터화는 간결하고 유연하다.