1. 팩토리 메서드 패턴 돌아보기
팩토리 메서드 패턴을 이용하여 리펙토링 했지만 찜찜함이 있었다. 간단한 팩토리에서 했던 분기 작업을 Controller 단으로 미룬 게 아닌가? 하는 생각 때문이었다.
헤드 퍼스트 디자인 패턴에서 예시로 들었던것도 팩토리 매서드 패턴을 적용한 타이밍은 팩토리의 종류(피자 매장의 타입) 자체가 달라지는 경우였다. 뉴욕 스타일의 피자 매장에서는 뉴욕스타일만 만들 것이고 클라이언트는 계속 그 요청만 하니 팩토리 자체를 추상화한 것이었다.
그래서 지금 내가 프로젝트의 상황에서는 팩토리 메서드 패턴 적용까지는 갈 필요가 없고 간단한 팩토리에서 타입에 따라 분리하는게 더 맞아 보인다. 지금 상황에서 새로운 댓글 타입이 추가된다면 TypesRository를 상속하는 클래스 한 개, CommentSerivce를 상속하는 클래스 한 개로 총 2개를 추가해야 하지만 간단한 팩토리를 이용하면 TypesRository 상속 클래스 하나만 추가하면 되니까.
2. 향상된 Simple Factory
향상된 간단한 팩토리 태그로 이동하여 코드를 확인해 보자.
https://github.com/SongHae8640/designPatternApply
GitHub - SongHae8640/designPatternApply
Contribute to SongHae8640/designPatternApply development by creating an account on GitHub.
github.com
git checkout tags/factory_simpleImprove
TypesRepository 가 타입을 갖게 하기 위해 추상 클래스로 변경하고 이를 상속하도록 변경한다.
public abstract class TypesRepository {
CommentType commentType;
abstract void checkTypesId(Long typesId);
abstract void addCommentCount(Long typesId);
CommentType getCommentType() {
return commentType;
}
}
@Component
public class TypesDrinkRepository extends TypesRepository {
private final DrinkRepository drinkRepository;
public TypesDrinkRepository(DrinkRepository drinkRepository) {
this.drinkRepository = drinkRepository;
this.commentType = CommentType.DRINK;
}
@Override
public void checkTypesId(Long typesId) {
drinkRepository.findById(typesId)
.orElseThrow(() -> new NoSuchElementException("존재하지 않는 음료입니다."));
}
@Override
public void addCommentCount(Long typesId) {
drinkRepository.findById(typesId)
.orElseThrow(() -> new NoSuchElementException("존재하지 않는 음료입니다."))
.addCommentCount();
}
}
@Component
public class TypesBoardRepository extends TypesRepository {
private final BoardRepository boardRepository;
public TypesBoardRepository(BoardRepository boardRepository) {
this.boardRepository = boardRepository;
this.commentType = CommentType.BOARD;
}
@Override
public void checkTypesId(Long typesId) {
boardRepository.findById(typesId)
.orElseThrow(() -> new NoSuchElementException("존재하지 않는 게시글입니다."));
}
@Override
public void addCommentCount(Long typesId) {
boardRepository.findById(typesId)
.orElseThrow(() -> new NoSuchElementException("존재하지 않는 게시글입니다."))
.addCommentCount();
}
}
팩토리 메서드 패턴의 클라이언트(Controller)에서는 댓글 타입을 map 의 key로 저장했던 방식을 SimpleFactory(RepositoryFactory)에 적용한다.
@Component
public class RepositoryFactory {
private final Map<CommentType, TypesRepository> repositoryMap;
public RepositoryFactory(List<TypesRepository> typesRepositoryList) {
this.repositoryMap = typesRepositoryList.stream()
.collect(java.util.stream.Collectors.toMap(TypesRepository::getCommentType, typesRepository -> typesRepository));
}
public TypesRepository getRepository(CommentType commentType) {
return repositoryMap.get(commentType);
}
}
3. 테스트

코드는 수정되었지만 테스트 코드 작성을 미리 해둔 덕분에 정상적으로 조회 및 저장된다는 것을 확인할 수 있다.
4. 후기
이렇게 팩토리를 적용해보면서 책으로만 읽었을 때랑은 다르게 더 깊은 고민을 해볼 수 있었다. 이후 다른 디자인 패턴도 내 프로젝트에서 적용해 보면서 디자인 패턴의 맛을 음미해 봐야겠다.
'개발' 카테고리의 다른 글
| Executing an update/delete query - 스케줄러에서 발생하는 예외가 API에서는 발생 했던 이유 (0) | 2025.11.12 |
|---|---|
| 디자인 패턴을 적용해보자 - 팩토리(3). (pizza 예제 아님) (0) | 2023.04.05 |
| 디자인 패턴을 적용해보자 - 팩토리(2). (pizza 예제 아님) (0) | 2023.04.05 |
| 디자인 패턴을 적용해보자 - 팩토리(1). (pizza 예제 아님) (0) | 2023.04.05 |
| JAVA HashMap의 용량은 왜 2의 거듭제곱일까? - 자료구조(9) (0) | 2022.05.30 |