[Java] 인자로 함수를 받는 고차함수를 통해 리팩토링 하기

2023. 11. 13. 22:08Java

아래의 두 함수를 보면 내용이 상당히 겹침을 알 수 있다. 다른 부분은 InputProcessor 클래스의 메소드와 그 인자로 넣어지는 InputView의 메소드이다. 즉, 어떤 메소드를 쓰는지만 달라진다. 그렇다면 인자로 함수를 넣어줘서 두 메소드를 하나로 합칠 수는 없을까?

    private static int getDate() {
        while (true) {
            try {
                return InputProcessor.processDateInput(InputView.readDate());
            } catch (IllegalArgumentException e) {
                System.out.println(e);
            }
        }
    }

    private static PreOrder getPreOrder() {
        while (true) {
            try {
                return InputProcessor.processMenu(InputView.readMenu());
            } catch (IllegalArgumentException e) {
                System.out.println(e);
            }
        }
    }

결론적으로 가능하다. 아래의 두 인터페이스를 활용하면 된다.

import java.util.function.Function;
import java.util.function.Supplier;

Function의 경우 설명에 다음과 같이 나타나 있다.

Represents a function that accepts one argument and produces a result.

즉, 하나의 인자를 받아서 결과를 만들어내는 함수를 나타낸다.

 

Supplier의 경우 설명에 다음과 같이 나타나 있다.

Represents a supplier of results.

결과를 제공하는 역할만 한다. 즉, 인자를 안받아도 결과를 제공하는 역할을 한다는 것이다.

 

이들을 이용해서 리팩토링하면 다음과 같이 된다.

    private static <T> T getInput(Function<String, T> processor, Supplier<String> inputSupplier) {
        while (true) {
            try {
                return processor.apply(inputSupplier.get());
            } catch (IllegalArgumentException e) {
                System.out.println(e);
            }
        }
    }

processor는 String 인자를 받아 타입 T를 리턴해주는 함수를 인자로 받는다.

inputSupplier는 String 인자로 리턴해주는 함수를 인자로 받는다.

제너릭 타입 T는 processor가 어떤 타입을 반환하는지에 유동성 있게 대처하기 위해 사용되었다.

inputSupplier가 get을 호출하게 되면 넣어준 메소드가 호출이 된다.

마찬가지로 processor가 apply를 호출하게 되면 넣어준 메소드가 호출이 된다. apply 안에는 실제 메소드에 넣어줄 인자를 넣어준다.

 

다음과 같이 사용된다.

        int date = getInput(InputProcessor::processDateInput, InputView::readDate);
        PreOrder preOrder = getInput(InputProcessor::processMenu, InputView::readMenu);

결과적으로 아주 깔끔하게 리팩토링이 된 것을 확인할 수 있다.

 

이렇듯 인자로 함수를 받는 함수를 고차함수라고 한다. 

Java8에서 도입된 Function과 같은 함수형 인터페이스로 가능해졌다.

 

Reference


https://ocwokocw.tistory.com/48

 

[Java 8] 객체로서의 함수

- https://flyingbytes.github.io/programming/java8/functional/part1/2017/01/23/Java8-Part1.html - 개요 Java 8 에서 함수는 1급 객체가 되었다. 이 말은 함수를 다른 함수의 인자가 되거나 반환형이 되거나 객체로 저장될

ocwokocw.tistory.com