복습) 템플릿 메서드 패턴
abstract 클래스에 공통로직을 구현하고, 비즈니스 로직은 클래스를 상속하여 구현
-> 비즈니스 클래스가 결국 공통로직을 가지고 있는 형태임, 부모의 수정에 영향을 받을 수 있음
번외) 익명클래스에서 람다변경 -> 인터페이스에 메서드 하나만 있을 때 가능
ContextV1 contextV1 = new ContextV1(new Strategy() {
@Override
public void call() {
log.info("비즈니스 로직1 실행");
}
});
ContextV1 contextV1 = new ContextV1(() -> log.info("비즈니스 로직1 실행"));
되돌아보는 우리의 목적
- 공통 로직을 여러 메서드에 추가하고 싶음
- 공통 로직을 추가할 때 기존 로직을 최대한 수정하지 않도록
- 공통 로직이 중복되지 않게
- 공통 로직과 비즈니스 로직이 섞이지 않게
전략 패턴
- 변하지 않는 부분(공통로직)은 context, 변하는 부분(비즈니스 로직)은 strategy 인터페이스를 만들고 해당 인터페이스를 구현해서 위임 임
- Context 안에서 strategy를 사용하고 호출부는 Context 사용
- 스프링에서 기본으로 채택하고 있는 패턴
- 클라이언트와 독립적으로 알고리즘 변경 가능
한계
- strategy를 필드로 가지는 Context 조립 끝낸 이후에, 전략을 변경하기 번거로움
- 세터주입으로 변경할 수 있겠지만, 만약 Context를 싱글톤으로 사용하면 동시성 이슈가 생길 수 있어, 새로 Context를 만드는 게 나을 것임
- 더 유연하게 전략 바꿀 수는 없을까? -> 실행하는 시점에 전략을 파라미터로 전달하기
템플릿 콜백 패턴
템플릿
변하는 코드와 변하지 않는 코드를 구분하는 것
콜백
다른 코드의 인수로 넘겨주는 실행 가능한 코드 (예시: 위의 strategy)
call되는데, 넘겨준 코드의 뒤쪽(back)에서 실행된다
템플릿 콜백 패턴
- 스프링에서 비즈니스 로직 클래스를 함수 파라미터로 받아 실행하는 패턴 (GoF의 패턴은 아니고, 스프링에서 이 방식을 자주 사용해 스프링에서 이렇게 부름)
- 전략패턴에서 템플릿과 콜백이 강조된 패턴
- 스프링의 xxxTemplate으로 네이밍된 클래스는 이 템플릿 콜백 패턴이 적용됨
디자인 패턴은 의도가 중요, 필드로 인수를 가지든지 파라미터로 받든지는 선택. 의도를 만족하면 됨.
한계
기존 로직에 손을 안 댈 수는 없음
본질적으로 코드를 수정해야 하는 것은 마찬가지 -> 프록시를 이용해 원본코드를 수정하지 않는 방법이 있다! to be continued..
단축키
인라인
코멘드 옵션 v
실행
컨트롤 쉬프트 R