Dev/Java

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

아콩2 2022. 5. 26. 22:59
반응형

동작 파라미터화 코드 전달하기 (1)에서 파라미터를 추가하는 방법이 아닌 변화하는 요구사항에 좀 더 유연하게 대응 할 수 있는 방법이 절실함을 확인 했다. 사과의 어떤 속성에 기초해서 불리언값을 반환 하는 방법이 있다. 참 또는 거짓을 반환하는 함수를 프리디케이트 라고 한다. 선택 조건을 결정하는 인터페이스를 정의해보자!

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

선택 조건을 대표하는 여러 버전의 ApplePredicate를 정의 해보자!

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

public class AppleGreenColorPredicate implements ApplePredicate {
    public boolean test(Apple appplKakaoTalk_Photo_2022-05-26-22-25-03e){
        return GREEN.equals(apple.getColor());
    }
}    

ApplePredicate는 사과 선택 전략을 캡슐화 하였다 -> 이를 전략 디자인 패턴 (Stragegy Design Pattern이라고 한다.

즉, 전략 디자인 패턴은 각 알고리즘(전략이라 불리는)을 캡슐화 하여 알고리즘 패밀리를 정의해둔 다음에 런타임에 알고리즘을 선택하는 기법이다.
(ApplePredicate가 알고리즘 패밀리이고 AppleHeavyWeightPredicate와 AppleGreenColorPredicate가 전략이다)

어떻게 ApplePredicate는 다양한 동작을 수행 할 수 있을까? filterApples에서 ApplePredicate 객체를 받아 애플의 조건을 검사하도록 메서드를 고쳐야 한다. 이렇게 동작 파라미터화 , 즉 메서드가 다양한 동작(또는 전략)을 받아서 내부적으로 다양한 동작을 수행 할 수 있다.

1. 네번째 시도 : 추상적 조건으로 필터링

public static List<Apple> filterApples(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> greenCololrApples = filterApple(inventory,new AppleGreenColorPredicate()); // 초록색 사과만 필터링 하도록 test메서드가 정의된 AppelPreicate 객체를 전달 

우리가 전달한 ApplePredicate 객체에 의해 filterApples 메서드의 동작이 결정된다 즉, 우리는 앞으로 변덕쟁이 농부의 요구사항에 따라 사과를 필터링 할 수 있는 ApplePredicate를 적절하게 구현하는 클래스만 만들면 된당 !
filterApples 메서드의 새로운 동작을 정의하는 것은 test 메서드 이다. 안타깝게도 메서드는 객체만 인수로 받기 때문에 test메서드를 ApplePredicate 객체로 감싸서 전달해야 한다. test메서드를 구현하는 객체를 이용해서 불리언 표현식 등을 전달할 수 있기 때문에 이는 코드를 전달 할 수 있는거나 다름이 없다. 이후에는 ApplePreicate클래스를 정의하지 않고 람다식을 이용해서 더 깔끔하게 코드 구현 을 하는 법을 알아보자!!


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

한 메서드가 다른 동작을 수행 할 수록 재활용 할 수 있다. 따라서 유연한 API를 만들 때 동작 파라미터화가 중요한 역할을 한다.

Quiz 1. 유연한 prettyPrintApple 구현하기 🍎

사과 리스트를 인수로 받아 다양한 방법으로 문자열을 생성(커스터마이즈 된 다양한 toString메서드 같이) 할 수 있도록 파라미터화된 prettyPrintApple메서드를 구현하시오. 예를들어 prettyPrintApple 메서드가 각각 사과 무게를 출력하도록 지시할 수 있다. 혹은 각각의 사과가 무거운지 가벼운지 출력하도록 지시할 수 있다. prettyPrintApple 메서드는 지금까지 살펴 본 필터링 예제와 비슷한 방법으로 구현할 수 있다.


public interface AppleFommater {
    String print(Apple apple);
}

public class PrintAppleWeight implements AppleFommater {
    String print(Apple apple){
        return "사과의 무게는" + apple.getWeight()+"g 입니다";
    }
}

public class PrintAppleWeightStatus implements AppleFommater {
    String print(Apple apple){
        String result = apple.getWeight() > 150 ? "무겁" : "가볍";
        return "이 사과는 "+ result+ "습니다.
    }
}


public void prettyPrintApple(List<Apple> apples, AppleFommater af){
    for(Apple a : apples){
        system.out.println(af.print(a));
     }
}

마무리

지금까지 동작을 추상화해서 변화하는 요구사항에 대응할 수 있는 코드를 구현하는 방법을 살펴봤다. 하지만 여러 클래스를 구현해서 인스턴스화하는 과정은 좀 많이 귀찮다. 어떻게 개선이 가능한지 다음시간에 알아보자~

반응형