티스토리 뷰

반응형

전략 패턴과 템플릿 콜백 패턴

 

템플릿 콜백 패턴은 전략 패턴을 발전시킨 형태이다.

전략 패턴은 보통 인터페이스와 그것들의 구현체(전략들, Strategy)를 생성해 놓고, Client 클래스가 구현체를 선택하여 그것을 실행시킬 Context 클래스에 주입하여 원하는 전략을 실행시키는 방식으로 구성된다. 이 패턴을 통해 여러 구현체를 만들어놓고, 상황에 따라 Client 클래스의 구현체 선택만을 바꾸는 방식으로 프로그램을 손쉽게 수정할 수 있다.

템플릿 콜백 패턴에선 전략 패턴과 다르게 전략들을 따로 만들어두지 않는다. 그 대신 익명 클래스를 사용해 Client 클래스에서 Context 클래스에 익명 클래스를 통해 전략을 바로 생성하여 주입한다.

 

템플릿 콜백 패턴을 통해 반복되는 로직을 뽑아내자

 

반복되는 오류 처리 로직

 

InputView라는 클래스에서 사용자의 입력을 받고 해당 입력이 단순 공백인지 등을 검사한다 가정하자. 단순 공백등의 입력이 들어왔을 때 InputView는 예외를 발생시키고, 예외가 발생하면 InputView 로직을 호출하는 Controller에서 예외 메시지를 출력하고 입력을 받는 로직을 무한히 수행한다 하자.

 

class Controller {
    void main() {

        ...

        String message = "";
        while(true) {
            try {
                message = InputView.readMessage();
                break;
            } catch(Exception e) {
                System.out.println(e.getMessage());
            }
        }

        ...

    }
}

 

설명한 과정을 수행하는 컨트롤러 로직은 위와 같다. while() 문을 사용해 예외가 발생한다면 계속 readMessage()를 반복하고 정상적인 입력이 들어왔다면 루프를 빠져나오게 된다.

이러한 방법에는 문제가 두 가지 있다.

  1. 컨트롤러에서 while() 내부의 try~catch 문이 사용자 로직을 입력받는 View의 로직을 호출할 때마다 반복된다.
  2. 컨트롤러의 한 메서드가 사용자 입력을 받아 처리, 오류 발생 시 재시도 로직 수행의 두 가지 책임을 가지게 된다.

이러한 경우 오류 처리 로직을 템플릿 콜백 패턴을 사용하여 분리해낼 수 있다.

 

 

템플릿 콜백 패턴을 통한 오류 처리 로직 분리

 

위에서 설명했듯 템플릿 콜백 패턴은 실제 전략에 대한 구현체를 일일이 만들지 않고 Client가 전략을 수행하는 Context클래스에 익명 클래스를 사용하여 특정한 전략을 넘겨준다.

 

Strategy

함수형 인터페이스를 사용해 생성할 전략을 정의한다. 람다식에 사용하기 위한 execute() 를 정의하였다.

@FunctionalInterface
public interface ExecuteStrategy<T> {

    T execute();
}

 

Context

클라이언트에서 넘겨주는 전략에 대한 Context, 처리 맥락을 정의한다. 우리가 공통 처리하고자 하는 예외 발생 시 무한한 사용자 재입력 로직을 여기서 처리한다.

public class ExecuteContext {

    public static <T> T workWithExecuteStrategy(ExecuteStrategy<T> executeStrategy) {
        T result = null;
        while (result == null) {
            try {
                result = executeStrategy.execute();
            } catch (Exception exception) {
                System.out.println(exception.getMessage());
            }
        }
        return result;
    }
}

 

Client

class Controller {   
    List<String> logic() {
        return ExecuteContext.workWithExecuteStrategy(() -> InputView.inputMultipleStrings());
    }
}

Client 클래스에서 사용할 전략에 대한 구현체를 직접 만들어 사용한다.

InputView의 다른 로직인 List을 넘겨주는 로직도 동일한 템플릿을 사용해 Context에 넘겨주어 처리할 수 있다.

 

 

위와 같이 템플릿 콜백 패턴을 사용하여 객체지향 5대 원칙 중 하나인 OCP를 강화할 수 있다.

반응형