인프런 스프링 - 고급편 강의 내용을 참고하여 정리한 내용입니다.
이전 포스팅에서 전략패턴으로 변경에 유연한 구조를 살펴보았지만, 전략패턴에도 문제가 있다.
그것은 바로 런타임에 원하는 전략으로 바꿔서 실행하기가 어렵다는 점이다. 새로운 전략을 사용하려면, context에 setter를 사용하여 변경하면 되지만 context가 싱글톤 객체라면 동시성 이슈 등 여러 문제가 생긴다.
그렇다면 전략패턴보다 유연하게 설계하는 방법은 없을까?
이번에는 context가 strategy를 필드로 가지고 있게 하는 것이 아니라, 메서드가 실행될 때마다 새로운 전략이 인자로 전달되는템플릿 콜백 패턴
을 알아보자.
여기서 콜백(callback)이란 다른 코드의 인수로서 넘겨주는 실행 가능한 코드를 말한다.
콜백을 넘겨받는 코드는 이 콜백을 필요에 따라 즉시 실행할 수도 있고, 아니면 나중에 실행할 수도 있다.
class Template {
fun execute(callback: Callback) {
val startTime = System.currentTimeMillis()
callback.call() // 위임
val endTime = System.currentTimeMillis ()
val resultTime = endTime - startTime;
log.info("resultTime={}", resultTime)
}
companion object : Log
}
@Test
fun callback() {
val template = Template()
val callback1 = CallbackLogic1()
template.execute(callback1)
val callback2 = CallbackLogic2()
template.execute(callback2)
}
예제 처럼 callback를 인자로 받으면 새로운 전략을 사용할 때마다 template 매번 새로 생성할 필요없이 유연한 변경을 기대할 수 있다.
템플릿 메서드 패턴, 전략 패턴, 템플릿 콜백 패턴 모두 공통적인 핵심은 변하는 부분과 변하지 않는 부분을 분리하여 유연하게 변경을 관리할 수 있다는 점이다.
하지만 이 같은 패턴에도 한계는 존재하는데, 최초에 적용하고자 하는 모든 클래스에 패턴 적용을 위한 변경이 필수적이라는 것이다. 클래스가 많은 애플리케이션이라면, 그 비용도 무시하진 못할 것이다.
이럴 때는 프록시 패턴을 사용하면, 원본코드를 사용하지 않고도 새로운 기능을 추가할 수 있는데 다음 포스팅에서 알아보자.