IT/Java

동작 파라미터화

김 정 환 2022. 8. 13. 17:41
반응형

 

동작 파라미터화를 사용하는 방법을 배워보려고 합니다.

 

어떤 문제를 해결하기 위해서 A 함수를 작성했다고 가정합니다. 그런데 A 함수에 대한 요구가 많아지면서, A 함수 내부에 조건문도 추가되고, 인자도 늘어나게 되는 경우가 있습니다. 이때 요구사항이 추가되더라도 기존 A 함수와 거의 비슷하다면 코드를 추상화할 수 없을까요? 구체적인 예시를 보겠습니다.

특정 과일을 골라내야 하는 문제가 있어서 이를 해결하기 위해서 아래 코드를 작성했습니다. busket에 담겨진 과일들 중에 '배'가 있으면 필터링해서 따로 담았습니다.

public static List<Fruit> chooseFruits(List<Fruit> busket){
  List<Fruit> chosenFruits = new ArrayList<>();
  for (Fruit fruit : busket){
     if(fruit.getType().equals(PEAR)){
       chosenFruits.add(fruit);
     }
  }
  return chosenFruits;
}

 

새로운 요구사항이 도착했습니다. 배 말고 다른 과일들도 선택하야 한다고 합니다. type을 인자로 만들어 주었습니다. 그런데 위에 코드와 굉장히 비슷합니다. 비슷한 형태를 가진 메서드를 만들었습니다. (뭔가 좋은 방법이 없을까...?)

public static List<Fruit> chooseFruits(List<Fruit> busket, String type){
  List<Fruit> chosenFruits = new ArrayList<>();
  for (Fruit fruit : busket){
     if(fruit.getType().equals(type)){
       chosenFruits.add(fruit);
     }
  }
  return chosenFruits;
}

 

새로운 요구사항이 또 도착했습니다. 이번에는 당도가 높은지 구분해 달라고 합니다. sweetness라는 인자를 만들어 주었습니다. (뭔가 좋은 방법이 없을까...?)

public static List<Fruit> chooseFruits(List<Fruit> busket, int sweetness){
  List<Fruit> chosenFruits = new ArrayList<>();
  for (Fruit fruit : busket){
     if(fruit.getSweetness() > sweetness){
       chosenFruits.add(fruit);
     }
  }
  return chosenFruits;
}

 

 

 

이렇게 비슷한 녀석인데 계속 새로 만들어야 하니 귀찮아졌습니다. 새로운 방법이 없을까요? 자바 8에서는 동작 파라미터화로 이 문제를 해결하고 있습니다. 

가정 먼저, 다르지만 비슷한 동작을 수행하는 녀석을 찾습니다. 위 예시에서는 과일의 종류와 당도 조건입니다. 이들을 추상화하면 될 것 같습니다. 아래와 같이 추상화 해보겠습니다. FruitPredicate라는 인터페이스를 만들고, 이를 구현하는 FruitTypePredicate와 FruitSweetnessPredicate를 구현했습니다. 이렇게 만든 것을 인수로 넣어주면 됩니다. (이러한 방법을 전략 패턴이라고 합니다.)

public interface FruitPredicate{
  boolean execute (Fruit fruit);
}

public class FruitTypePredicate implements FruitPredicate{
  public boolean execute (Fruit fruit){
    return fruit.getType().equals(PEAR);
  }
}

public class FruitSweetnessPredicate implements FruitPredicate{
  public boolean execute (Fruit fruit){
    return fruit.getStweetness() > 10;
  }
}

 

 

위에서 만든 것을 메서드에 넣어보겠습니다. 넣을 메서드를 만들어주고 넣어줍니다. 이렇게 FruitPredicate만 넣어준다면 기존 메서드는 보존한 상태에서 다양한 동작을 수행할 수 있습니다. 이것이 함수형 프로그래밍입니다.

// 넣을 메서드
public static List<Fruit> chooseFruits(List<Fruit> busket, FruitPredicate p){
  List<Fruit> chosenFruits = new ArrayList<>();
  for (Fruit fruit : busket){
    if(p.execute(fruit)){
      chosenFruits.add(fruit);
    }
  }
  return chosenFruits;
}

// 메서드에 넣기
List<Fruit> result = chooseFruits(busket, new FruitTypePredicate);

 

위에서 설명한 내용을 아래 그림으로 마무리하면 될 것 같습니다. 사용한 naming은 다르지만 같은 코드입니다. 새로운 동작을 하는 메서드를 만들어서 넣어줄 수 있습니다.

 

만약에 넣어주는 코드가 간단하다면 람다식으로 작성할 수 있습니다. 그러나 복잡한 로직이 필요한 경우에는 직접 만들어 주는 것이 좋습니다.

List<Fruit> result = chooseFruits(busket, (Fruit fruit) -> fruit.getType().equals(PEAR));

 

 

이렇게 함수형 프로그래밍의 특징 중 하나인 '메서드의 인자로 메서드 넣기'를 알아봤습니다.

끝.

반응형

'IT > Java' 카테고리의 다른 글

Arrays.asList() vs ArrayList()  (0) 2022.12.19
팩토리 패턴 (Factory Pattern)  (0) 2022.11.07
[함수형 데이터 처리] 스트림  (2) 2022.09.25
기본형과 참조형 변수  (0) 2022.09.04
자바 8 등장  (0) 2022.08.13