템플릿 메서드, 전략, 콜백 패턴에 대해서 알아보자
들어가며
애플리케이션을 개발할 때 템플릿 메서드 패턴이나 콜백패턴을 사용하지 않고 실행 시 로그를 작성해 주는 기능을 개발했다고 해보자. 그러면 try~catch 같은 예외처리를 잡는 문법이 무수히 많은 곳에 작성되면서 코드의 가독성을 낮아지게 한다. 그래서 템플릿 메서드 패턴과 콜백패턴을 알아보고 이러한 패턴들을 사용해 코드의 가독성을 높여 유지보수를 하기 쉽게 하는 방법을 알아보자
템플릿 메서드 패턴
템플릿 메서드 패턴이란?
객체지향 프로그래밍에서 사용하는 패턴 중 하나이다. 메서드 패턴은 상위 클래스의 사용할 알고리즘의 큰 틀을 만들어두고 변경이 되는 알고리즘을 하위에 클래스의 재 정의하여 구체화할 수 있는 기법을 말합니다. 이를 통해 중복된 코드를 줄이고 유지보수를 쉽게 만들 수 있습니다.
템플릿이란?
템플릿은 공통적인 부분을 정의해놓은 클래스입니다. 템플릿 안에는 정적인 부분과 동적인 부분을 정의해 놓고, 동적인 부분을 따로 정의함으로써 유연하게 사용할 수 있도록 합니다.
템플릿 메서드 코드 예시
@Slf4j
public abstract class AbstractTemplate {
public void execute(){
log.info("템플릿 메서드 시작");
call();
log.info("템플릿 메서드 종료");
}
protected abstract void call();
}
전체 코드의 틀을 추상화 클래스로 만들어줬다.
execute() 메서드를 사용하면 call 메서드가 호출되며 사용자가 작성한 서브 클래스를 사용한다.
//서브클래스
@Slf4j
public class SubClass1 extends AbstractTemplate{
@Override
protected void call() {
log.info("1 실행");
}
}
@Slf4j
public class SubClass2 extends AbstractTemplate{
@Override
protected void call() {
log.info("2 실행");
}
}
사용자가 작성한 두 개의 서브클래스 작성
void templateMethodV1(){
AbstractTemplate template1 = new SubClass1();
template1.execute();
AbstractTemplate template2 = new SubClass2();
template2.execute();
}
다음과 같이 추상 메서드에 직접 사용할 서브클래스를 정의하고 실행해 보면
call() 메서드 부분이 서브클래스로 작성한 클래스가 사용되는 것을 볼 수 있다.
하지만 서브클래스 별로 만들어서 사용하면 파일을 생성해야 하는 번거로움이 발생한다. 그랬을대 자바 문법의 익명 내부 클래스를 사용한다면 손쉽게 만들 수도 있다.
익명 내부클래스 사용
void templateMethodV2() {
AbstractTemplate template1 = new AbstractTemplate() {
@Override
protected void call() {
log.info("익명 내부 클래스1 실행");
}
};
template1.execute();
AbstractTemplate template2 = new AbstractTemplate() {
@Override
protected void call() {
log.info("익명 내부 클래스2 실행");
}
};
template2.execute();
}
직접 사용할 클래스 생성해 사용하지 않고 익명 내부 클래스를 활용한 템플릿 메서드
템플릿 메서드 다이어그램
클라이언트가 call()을 요청을하면 개발자가 정의한 subClass1이나 subClass2가 적절히 사용하게 된다.
템플릿 메서드 장, 단점
장점
- 코드의 재사용성
- 유연성
- 중복 코드 제거
단점
- 확장의 어려움 : 상속 기반으로 작동하기 때문에 확장이 제한될 수 있다.
- 복잡성 : 템플릿 메서드 패턴을 적용한다면 상위클래스와 하위 클래스의 관계를 명확히 알고 사용해야 하기 때문에 복잡해질 수 있다. 또한 추상메서드를 통해 사용해야 하기 때문에 오버헤드가 증가할 수 있다.
전략(Strategy) 패턴
전략 패턴이란?
전력 패턴은 알고리즘을 캡슐화하고 해당 알고리즘을 동적으로 사용하기 위해서 만든 패턴이다. 전략패턴은 클라이언트와 알고리즘을 독립적으로 분리하여 유연성을 제공한다. 전력패턴은 다음과 같은 세 가지 요소로 구성되어 있다.
- 전략(Strategy) : 알고리즘을 캡슐화하는 인터페이스 또는 추상화 클래스.
- 구체적인 전략(Concrete Strategy) : 전략 인터페이스를 구현한 구체적인 알고리즘을 담은 클래스
- 컨텍스트(Context) : 전략 객체를 사용하는 클라이언트
전략 패턴 코드 예시
전략 패턴을 사용하기 위해서 인터페이스를 설계해줘야 한다.
Strategy.Interface(전략)
public interface Strategy {
void call();
}
간단하게 call() 메서드를 담은 Strategy인터페이스를 작성 (전략이라고 할 수 있다.)
Strategysub.class(구체적인 전략)
public class StrategyLogic1 implements Strategy{
@Override
public void call() {
log.info("로직1 실행");
}
}
@Slf4j
public class StrategyLogic2 implements Strategy{
@Override
public void call() {
log.info("로직2 실행");
}
}
Strategy의 인터페이스를 구현한 두 개의 구현체
Context.class(콘텍스트)
@Slf4j
public class Context {
public void execute(Strategy strategy){
log.info("전력패턴 실행");
strategy.call(); //위임
log.info("전략 패턴 종료");
}
}
전략을 사용할 Context를 작성해 준다.
void strategyV1() {
ContextV2 context = new ContextV2();
context.execute(new StrategyLogic1());
context.execute(new StrategyLogic2());
}
다음과 같이 컨텍스트에서 공통으로 실행되는 실행, 종료는 사용되며 변하는 로직 부분만 다르게 출력된 것을 볼 수 있다.
전략패턴 다이어그램
전략 패턴 장, 단점
장점
- 유연성
- 재사용성
- 유지보수성
단점
- 클래스 수 증가 : 전략패턴을 사용하면 각각의 기능에 맞게 클래스를 생성해야 한다( 익명클래스를 사용해 클래스수를 주를 수 있지만, 가독성이 감소함)
- 클라이언트 인지 부담 : 템플릿 메서드처럼 모든 전략을 이해하고 있어야 자요롭게 사용가능한다는 부담감
콜백(Callback) 패턴
콜백(Callback) 패턴이란?
프로그래밍에서 콜백(callback) 또는 콜애프터 함수(call-after function)는 다른 코드의 인수로서 넘겨주는 실행 가능한 코드를 말한다. 콜백을 넘겨받는 코드는 이 콜백을 필요에 따라 즉시 실행할 수도 있고, 아니면 나중에 실행할 수도 있다.
전략 패턴에서 public void execute(Strategy strategy) 메서드 부분에서 파라미터로 넘기는 Strategy 객체를 콜백역할을 합니다. 즉, 전략 패턴에서는 클라이언트가 선택한 전략을 콜백으로 사용하여 특정 동작을 실행하게 됩니다.
콜백 패턴 코드 예시
전략 패턴과 같이 인터페이스를 작성합니다.
public interface Callback {
void call();
}
이제 템플릿 클래스를 작성합니다.
@Slf4j
public class CallbackTemplate {
public void execute(Callback callback){
log.info("템플릿 클래스 실행");
callback.call(); //위임
log.info("템플릿 클래스 종료");
}
}
이번 콜백 패턴에서는 Callback.interface의 구현 클래스를 작성하지 않고 익명 내부 클래스를 사용하겠습니다.
void callBack(){
CallbackTemplate timeLogTemplate = new CallbackTemplate();
timeLogTemplate.execute(new Callback() {
@Override
public void call() {
log.info("로직 1 실행");
}
});
timeLogTemplate.execute(new Callback() {
@Override
public void call() {
log.info("로직 2 실행");
}
});
}
Spring에서 제공하는 xxxTemplate는 위와 같은 방식으로 동작한다.
정리
- 템플릿 메서드 패턴 (Template Method Pattern)
- 상위클래스에서 알고리즘을 정리하고 하위 클래스에 구체적인 알고리즘을 정의하여 사용하는 패턴
- 공통적인 부분을 상위에 작성 변경되는 내용을 하위클래스에 작성
- 코드가 중복을 줄이고, 가독성과 유지보수성을 향상
- 전략 패턴 (Strategy Pattern)
- 알고리즘을 캡슐화하여, 클라이언트에서 동적으로 알고리즘을 교체할 수 있는 패턴
- 각각의 알고리즘을 별도의 클래스로 정의하고, 이를 인터페이스를 통해서 제공
- 콜백 패턴(Callback Pattern)
- 매개변수로 전달하여 호출하는 디자인패턴
'Spring > spring' 카테고리의 다른 글
[Spring] 스프링 컨테이너와 싱글톤 컨테이너 (0) | 2024.02.29 |
---|---|
[Spring] 스프링의 객체지향 원리 간단하게 이해하기 (0) | 2024.02.28 |
[Spring] 스프링에서의 필터(filter)와 인터셉터(Interceptor) (1) | 2024.02.06 |
[스프링] AOP(Aspect-Oriented-Programming)이해 (0) | 2023.11.22 |
[스프링] 트랜잭션(Transaction)이란 (0) | 2023.11.22 |