
토비님의 스프링 강의에서 템플릿 메서드 패턴과 전략 패턴을 학습하고, 사이드에서 적용해보았습니다.
public abstract class AuthStrategyImpl implements AuthStrategy {
...
@Override
public void execute(final Long adminId, final String apiTokenUuid, final Object resourceId,
final AccessLevelType accessLevelType) {
final List<Long> placeIds = this.get...(this.getPlaceId(resourceId),
accessLevelType);
...
}
protected abstract Long getPlaceId(Object resourceId);
private List<Long> getPlace...(final Long placeId,
final AccessLevelType accessLevelType) {
return this.placeRepository.find...(placeId).map(
parents -> {...}
).orElseThrow(() -> new PermissionDeniedException("Place not found"));
}
}
제 의도는 execute 를 구현하는 클래스를 여러 개 생성하여 갈아끼우는 방식이었습니다.
근데 설계를 해놓고 나니 정작 execute 부분은 변동이 없었습니다.
오히려 getPlaceId 부분이 각 클래스마다 변경되는 것 같아서,
하나의 추상 클래스로 execute 를 통합하고 추상 클래스를 상속받는 각 구현체에서
getPlaceId 를 구현하도록 했습니다.
이렇게 하다 보니 나는 분명 템플릿 메서드 패턴 & 전략 패턴으로 아키텍처를 설계했다고 생각했는데,
execute 가 바뀌는 대상이 아니라 getPlaceId 가 바뀌는 대상이 되면서
그냥 전형적인 템플릿 메서드 패턴이 되었습니다.
그래서, getPlaceId 를 분리하여 이 부분을 extractor 로 규정하고 개별 클래스로 분리하였습니다.
AuthStrategyImpl 는 그냥 하나의 AuthorizeExecutor 가 되었고,
PlaceIdExtractor 인터페이스를 활용하여 PlaceId 를 추출하는 형태로 개선되었습니다.
어떤 부분이 변동이 없는 부분이고 어떤 부분이 구현이 필요한 부분인지를 명확하게
진단하지 못한 저의 짧은 생각이었습니다.
하지만 이런 실수를 겪으면서 좀 더 손에 익는것 아닐까 그런생각이 듭니다.
아키텍처는 어렵기 때문에 역시 적용 훈련이 필요한 거 같습니다.