Design Pattern

[디자인 패턴] 템플릿 메서드 패턴과 콜백 패턴

꾸준함. 2021. 11. 25. 03:23

개요

강의에서 설명해주시는 좋은 설계란 SOLID 원칙 중 단일 책임 원칙(SRP)을 철저히 따라 최소한의 코드 변경을 통해 로직을 변경할 수 있는 구조라고 하셨습니다.

즉, 변경 지점을 한 곳에 모아 변경에 쉽게 대처할 수 있는 구조를 만드는 것이 핵심인데 이를 달성하기 위해 이번 게시글에서는 템플릿 메서드 패턴과 콜백 패턴에 대해 간단히 알아보겠습니다.

 

1. 템플릿 메서드 패턴

GOF(Gang Of Four) 디자인 패턴에 의하자면 템플릿 메서드의 정의는 아래와 같습니다.

"작업에서 알고리즘의 골격을 정의하고 일부 단계를 하위 클래스로 연기하는 것이 목적입니다. 템플릿 메서드를 사용하면 하위 클래스가 알고리즘의 구조를 변경하지 않고도 알고리즘의 특정 단계를 재정의할 수 있습니다."

 

여기서 핵심은 재사용을 위해 공통적인 부분은 부모 클래스에 알고리즘의 골격인 템플릿을 정의하고, 변경되는 로직은 자식 클래스에 정의하는 것입니다,

정리하자면 상속과 오버라이딩을 통한 다형성으로 재사용성이 높은 코드를 작성할 수 있는 것입니다.

 

템플릿 메서드 (https://reactiveprogramming.io/blog/en/design-patterns/template-method)

 

1.1 AbstractTemplate 클래스 예제

 

 

 

1.2 AbstractTemplate을 상속받는 ImplementationA와 ImplementationB 템플릿 메서드 패턴

 

 

1.3 AbstractTemplate을 익명 내부 클래스로 사용하는 템플릿 메서드 패턴


 

1.4 템플릿 메서드 패턴의 장단점

 

장점

  • 부모 클래스에 알고리즘의 골격인 템플릿을 정의하고 변경될 수 있는 로직은 자식 클래스에 정의하여 알고리즘이 변경되었을 때 전체 구조를 변경하지 않고 특정 부분만 재정의 가능
  • 부모 클래스가 바뀌지 않는다는 전제하에 훌륭한 구조

단점

  • 상속을 사용하기 때문에 상속에서 오는 단점들을 그대로 안고 감
    • 자식 클래스가 부모 클래스와 컴파일 시점에 강 결합되어 의존관계에 대한 문제 발생
    • 자식 클래스 입장에서는 부모 클래스의 기능을 전혀 사용하지 않지만 부모 클래스를 상속받아야 하고 이는 곧 특정 부모 클래스를 의존한다는 뜻
  • 즉, 부모 클래스가 변경되면 자식 클래스에도 영향이 끼칠 수밖에 없는 구조

 

2. 전략 패턴

  • 템플릿 메서드 패턴과 유사한 역할을 하면서 상속의 단점을 제거할 수 있는 디자인 패턴
  • 변하지 않는 부분을 Context라는 곳에 두고, 변하는 부분을 Strategy라는 인터페이스를 만들어 해당 인터페이스를 구현하도록 해서 문제를 해결
    • 상속이 아닌 위임으로 문제를 해결
  • 정리를 하자면 Context가 템플릿 메서드 패턴의 템플릿 역할을 하고, Strategy가 변하는 로직 역할을 함

 

https://reactiveprogramming.io/blog/en/design-patterns/strategy

 

2.1 필드에 전략을 보관하는 전략 패턴


 

2.1.1 익명 내부 클래스를 사용


 

2.1.2 익명 내부 클래스 사용 2


 

2.1.3 람다 사용


 

* 람다로 변경하려면 인터페이스에 메서드가 단 1개만 있어야 합니다. 2개 이상부터는 위와 같은 방법으로는 불가능

 

2.1.4 필드에 전략을 보관하는 전략 패턴 장단점

 

장점

  • Context와 Strategy를 실행 전에 원하는 모양을 조립해두고, 이후 Context를 실행하는 선 조립 후 실행 방식에 매우 유용
    • 스프링 환경에서 개발할 때 애플리케이션 로딩 시점에 의존관계 주입을 통해 필요한 의존관계를 모두 맺어두고 실제 요청을 처리하는 것과 같은 원리

단점

  • Context와 Strategy를 조립하나 이후에 전략을 변경하기가 매우 번거로움
    • setter를 제공하여 전략을 넘겨받는 방식으로 해결 가능하지만 스프링 프레임워크의 경우 컨테이너에 의해 싱글턴으로 관리되기 때문에 고려할 점이 많음
    • 따라서, 전략을 실시간으로 변경해야 할 경우 차라리 Context를 하나 더 생성하여 다른 전략을 주입받는 것이 더 나은 선택

 

2.2 전략을 파라미터로 전달해서 사용하는 패턴


 

2.2.1 익명 내부 클래스 사용


 

2.2.2 람다 사용

 

 

2.2.3 전략을 파라미터로 전달해서 사용하는 패턴 장단점

 

장점

  • 실행할 때마다 전략을 유연하게 변경 가능
    • 개발할 때마다 Waterfall 방식처럼 진행할 수 없기 때문에 Version 2가 더 적합

단점

  • 실행할 때마다 전략을 매번 지정해줘야 하는 번거로움

 

3. 템플릿 콜백 패턴

 

콜백이란?

  • 앞서 살펴본 전략을 파라미터로 전달해서 사용하는 전략 패턴처럼 다른 코드의 인수로서 넘겨주는 실행 가능한 코드를 콜백이라 함
    • 콜백을 넘겨받는 코드는 이 콜백을 필요에 따라 즉시 실행하거나 나중에 실행 가능
  • 정리를 하자면, callback은 코드가 호출은 되는데 코드를 넘겨준 곳의 백단에서 실행됨

 

3.1 템플릿 콜백 패턴

  • 콜백 정의를 할 때 설명한 것처럼 ContextVersion2와 같은 방식이 템플릿 콜백 패턴
    • Context가 템플릿 역할
    • Strategy 부분이 콜백
  • GOF 패턴은 아니지만 스프링 프레임워크 내부에서 자주 사용하기 때문에 필수로 알아야 하는 패턴
  • 스프링 프레임워크 내 JdbcTemplate, RestTemplate, RedisTemplate,... 와 같이 XXXTemplate 클래스들은 모두 템플릿 콜백 패턴으로 생각해도 됨

 

3.2 템플릿 콜백 패턴 예제

 

 

참고

인프런 스프링 핵심 원리 - 고급편 (김영한 강사님)

 

 

반응형