해당 장에서는 Behavior Parameterization을 통해 다양한 이점을 누릴 수 있는 것을 보여줍니다.
동작 파라미터화란 아직은 어떻게 실행할 것인지 결정하지 않은 코드 블록을 의미한다. 코드 블록의 실행을 나중으로 미뤄, 나중에 실행될 메서드의 인수로 코드 블록을 전달할 수 있다.
predicate : 참 또는 거짓을 반환하는 함수
public interface ApplePredicate {
boolean test (Apple apple);
}
public class WeightPredicate implements ApplePredicate {
public boolean test(Apple apple) {
return apple.getWeight() > 150;
}
}
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);
}
}
}
해당 방식은 ApplePredicate 인터페이스에 대한 구현체를 각각 만들어주어야 한다는 점에서 번거로울 수 있다. 물론, 반복적으로 사용해야 한다면 해당 방식이 좋을 수 있다.
public interface ApplePredicate {
boolean test (Apple apple);
}
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);
}
}
}
// 사용
List<Apple> apples = filterApples(inventory, new ApplePredicate() {
public boolean test(Apple apple) {
return apple.getWeight() > 150;
}
}
해당 방식은 따로 클래스를 선언해 사용하는 것이 아닌, 익명 클래스를 활용해 즉석에서 만들어서 사용한다. 해당 방식은 유용하지만, 가독성면에서 좋지 않을 수 있다.
//사용
List<Apple> apples = filterApples(inventory, (Apple apple) -> RED.equals(apple.getColor()));
람다 표현식을 활용하면 코드의 군더더기를 제거할 수 있다.