[Java8] 동작 파라미터화 코드 전달하기

동작 파라미터화 코드 전달하기

목차

변화하는 요구사항 대응하기

첫 번째 시도: 녹색 사과 필터링

List<Apple> inventory = Arrays.asList(new Apple(80,"green"), new Apple(155, "green"), new Apple(120, "red"));
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;
}

// 실행 코드
List<Apple> greenApples = filterApplesByColor(inventory);

두 번째 시도: 색을 파라미터화

public static List<Apple> filterApplesByColor(List<Apple> inventory, String color){
    List<Apple> result = new ArrayList<>();
    for(Apple apple: inventory){
        if(apple.getColor().equals(color)){
            result.add(apple);
        }
    }
    return result;
}

// 실행 코드
List<Apple> greenApples = filterApplesByColor(inventory, "green");
List<Apple> redApples = filterApplesByColor(inventory, "red");

동작 파라미터화

사과를 선택하는 다양한 전략

interface ApplePredicate{
	public boolean test(Apple a);
}

static class AppleWeightPredicate implements ApplePredicate{
	public boolean test(Apple apple){
		return apple.getWeight() > 150;
	}
}

static class AppleColorPredicate implements ApplePredicate{
	public boolean test(Apple apple){
		return "green".equals(apple.getColor());
	}
}

세 번째 시도: 추상적 조건으로 필터링

public static List<Apple> filter(List<Apple> inventory, ApplePredicate p){
    List<Apple> result = new ArrayList<>();
    for(Apple apple : inventory){
        if(p.test(apple)){
            result.add(apple);
        }
    }
    return result;
}    

// 실행
List<Apple> heavyApples = filter(inventory, new AppleWeightPredicate());
List<Apple> redAndHeavyApples = filter(inventory, new AppleRedAndHeavyPredicate());

불필요한 코드

한 개의 파라미터, 다양한 동작

복잡한 과정 간소화

네 번째 시도: 익명 클래스 사용

List<Apple> redApples2 = filter(inventory, new ApplePredicate() {
    public boolean test(Apple a){
        return a.getColor().equals("red");
    }
});

다섯 번째 시도: 람다 표현식 사용

List<Apple> result = filter(inventory, (Apple apple) -> "red".equals(apple.getColor()));

여섯 번째 시도: 리스트 형식으로 추상화

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 apple) -> "red".equals(apple.getColor()));
List<String> evenNumber = filter(numbers, (Integer i) -> i % 2 == 0);

실전 예제

Comparator로 정렬하기

// java.util.Comparator
public interface Comparator<T> {
  public int compare(T o1 , T o2);
}
inventory.sort(new Comparator<Apple>() {
        public int compare(Apple o1, Apple o2) {
            return o1.getWeight().compareTo(o2.getWeight());
        };
});
inventory.sort( (Apple o1, Apple o2) -> o1.getWeight().compareTo(o2.getWeight()));

Runnable로 코드 블록 실행하기

// java.lang.Runnable
public interface Runnable {
  public void run();
}
Thread t = new Thread(new Runnable() {
  public void run() {
    System.out.println("Hello world");
  }
});
Thread t = new Thread(() -> System.out.println("Hello world"));

요약