동작 파라미터화
계속 변화하는 요구조건에 최소한의 비용으로 계속 대응하기 위하는 것은 프로그래머에게 중요한 요소이다.
동작 파라미터화를 이용하면 이러한 변화에 더 쉽게 대응할 수 있다. 이를통해 유지보수가 쉬워진다.
동작 파라미터화가 할 수 있는 기능
- 리스트의 모든 요소에 대해 `어떤 동작` 수행 가능
- 리스트 관련 작업을 끝낸 후 `어떤 다른 동작`이 가능
- 에러가 발생하면 `정해진 다른 동작` 수행 가능
아래는 실제 책에서 제공했던 예시이다.
[만약 : 초록색일 때만 수집한다면]
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;
}
이렇게 바뀔거고 둘다 필요하면 또 변경하게 된다 이렇게 되면 유지보수 측면에서 엄청난 비용이 소모된다.
이러한 문제를 해결하기 위해 사용되는 것이 동작 파리머화이다. 말 그대로 동작을 넘겨준다 생각하면 된다.
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;
}
});
이렇게 익명 클래스를 통해서 특정 클래스를 override하고 해당 메서드를 동작시킨다.
이로서 override된 메서드 기능을 요구사항이 변경될 때마다 변경하면 된다.
하지만 아직 문제점이 있다. 바로 `익명 클래스`이다.
익명 클래스를 구현하기 위해서는 상속받기 위한 인터페이스가 존재해야 하는데, 특정 기능마다 인터페이스를 구현하고 오버라이딩하게 된다면 상당한 비용이 들고 유지보수가 힘들 것이다.
따라서 사용하는 것이 람다(labmda)이다.
List<Apple> redApples2 = filterGreenApples4(inventory, Apple apple -> apple.getColor() == Color.RED)
List<Apple> redApples2 = filterGreenApples4(inventory, Apple apple -> apple.getWeight() > 150)
람다를 통해 인터페이스의 구현없이 위와 같이 변경할 수 있다.
'JAVA > Java in action' 카테고리의 다른 글
[자바 인 액션] 6. 스트림 데이터 수집 (0) | 2023.03.23 |
---|---|
[자바 인 액션] 5. 스트림 활용 (0) | 2023.03.23 |
[자바 인 액션] 4. 스트림 (0) | 2023.03.23 |
[자바 인 액션] 3. 람다 표현식 (0) | 2023.03.23 |
[자바 인 액션] 1. 자바의 변화 (0) | 2023.03.22 |