(Java 실행) 2. 액션 매개변수화

동작 매개변수화


계속해 최소한의 비용으로 변화하는 요구에 지속적으로 대응수행은 프로그래머에게 중요한 요소입니다.

작동 매개변수화를 통해 이러한 변화에 보다 쉽게 ​​대응할 수 있습니다. 이런 이유로 손쉬운 유지 보수잃다

이동을 매개변수화하는 기능

  • 목록의 각 항목에 대해 “무슨 행동”. 할 수있어
  • 목록 작성을 마친 후 ‘다른 행동’가능하다
  • 오류가 발생했을 때 `다른 지정된 작업` 할 수있어

아래는 실제 책의 예입니다.

(If: 녹색인 경우에만 수집)

public static List<Apple> filterGreenApples(List<Apple> inventory) {
    List<Apple> result  new ArrayList<>();
    for (Apple apple : inventory) {
        if (apple.getColor() == Color.GREEN) {
            result.add(apple);
        }
    }
    return result;
}

위와 같이 작성했는데 요구사항이 변경되면 내부 조건문도 변경해야 합니다.

여기서 청사과가 아닌 다른 색상을 선택하고 싶다면

/**
 * List<Apple> greenApples = filterApplesByColor(inventory, Color.GREEN); 으로 사용 가능
 */
public static List<Apple> filterGreenApples2(List<Apple> inventory, Color color) {
    List<Apple> result = new ArrayList<>();
    for (Apple apple : inventory) {
        if (apple.getColor() == color) {
            result.add(apple);
        }
    }
    return result;
}

위와 같이 매개변수화하여 변경할 수 있습니다. 하지만 만약 상태가 증가하고 일반화되면 이 부분을 매개변수화한 다음 매개변수의 수가 크게 증가합니다..

색상이 아닌 크기별로 이름을 지정하고 싶다면?

public static List<Apple> filterGreenApples3(List<Apple> inventory, int size) {
    List<Apple> result = new ArrayList<>();
    for (Apple apple : inventory) {
        if (apple.getWeight() == size) {
            result.add(apple);
        }
    }
    return result;
}

그렇게 바뀌고 둘 다 필요할 때 다시 바뀌기 때문에 유지 보수에 많은 돈을 먹습니다.

이 문제를 해결하기 위해 작업 parimization이 사용됩니다. 말 그대로 행동을 넘겨주는 것으로 생각할 수 있습니다.

interface ApplePredicate {
    boolean test(Apple a);
}

// class 내부
public static List<Apple> filterGreenApples4(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> redApples2 = filterGreenApples4(inventory, new ApplePredicate() {
     @Override
     public boolean test(Apple a) {
     	return a.getColor() == Color.RED;
     }
});

이런 식으로 특정 클래스를 익명 클래스로 재정의하고 적절한 메서드를 실행합니다.

결과적으로 필요에 따라 재정의된 메서드의 기능을 변경합니다.할 수 있어요.

그러나 지금 문제있는 즉시 “익명의 클래스”.오전.

익명 클래스를 구현하기 위해서는 상속받을 인터페이스가 존재해야 하는데, 특정 기능별로 인터페이스를 구현하고 오버라이드하면 상당한 비용이 들고 유지보수가 어렵다.

그래서 사용 람다오전.

List<Apple> redApples2 = filterGreenApples4(inventory, Apple apple -> apple.getColor() == Color.RED)
List<Apple> redApples2 = filterGreenApples4(inventory, Apple apple -> apple.getWeight() > 150)

Lambda를 통해 인터페이스를 구현하지 않고 위와 같이 변경할 수 있습니다.