1. 팩토리 메서드 패턴 적용
이전 포스팅에서는 간단한 팩토리(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_method
팩토리 메서드 패턴은 객체 생성을 서브 클래스로 분리하는 디자인 패턴이다. 사용하는 클라이언트에서 경우에 따라 의존관계 역전을 이용하는데 코드로 표현하면 다음과 같다.
public abstract class CommentService {
CommentRepository commentRepository;
CommentType commentType;
public List<Comment> getCommentList(CommentType commentType, Long typesId) {
getTypesRepository()
.checkTypesId(typesId);
return commentRepository.findAllByCommentTypeAndTypesId(commentType, typesId);
}
public Comment saveComment(Comment comment) {
getTypesRepository()
.addCommentCount(comment.getTypesId());
return commentRepository.save(comment);
}
public CommentType getCommentType() {
return commentType;
}
abstract public TypesRepository getTypesRepository();
}
@Service
public class CommentServiceBoardImpl extends CommentService {
private final TypesBoardRepository typesBoardRepository;
public CommentServiceBoardImpl(CommentRepository commentRepository, TypesBoardRepository typesBoardRepository) {
this.commentRepository = commentRepository;
this.commentType = CommentType.BOARD;
this.typesBoardRepository = typesBoardRepository;
}
@Override
public TypesRepository getTypesRepository() {
return this.typesBoardRepository;
}
}
@Service
public class CommentServiceDrinkImpl extends CommentService {
private final TypesDrinkRepository typesDrinkRepository;
public CommentServiceDrinkImpl(CommentRepository commentRepository, TypesDrinkRepository typesDrinkRepository) {
this.commentRepository = commentRepository;
this.commentType = CommentType.DRINK;
this.typesDrinkRepository = typesDrinkRepository;
}
@Override
public TypesRepository getTypesRepository() {
return this.typesDrinkRepository;
}
}
CommentService를 추상 클래스로 변경하고 객체를 생성하는 메서드만 추상 메서드로 만들었다. 그리고 구현 클래스에서 객체 생성을 담당하게 하였다.
클라이언트(Controller)에서는 구현 클래스를 타입별로 Map으로 저장해서 사용하였다.
@RestController
@RequestMapping("/api/comments")
public class CommentController {
private final Map<CommentType, CommentService> commentServiceMap;
public CommentController(List<CommentService> commentServiceList) {
this.commentServiceMap = commentServiceList.stream()
.collect(Collectors.toMap(CommentService::getCommentType, commentService -> commentService));
}
@GetMapping
public List<Comment> getCommentList(@RequestParam String commentType, @RequestParam Long typesId) {
return commentServiceMap.get(CommentType.of(commentType))
.getCommentList(CommentType.of(commentType), typesId);
}
@PostMapping
public Comment saveComment(@RequestBody CommentDto commentDto) {
return commentServiceMap.get(CommentType.of(commentDto.getCommentType()))
.saveComment(Comment.builder()
.commentType(CommentType.of(commentDto.getCommentType()))
.typesId(commentDto.getTypesId())
.writerName(commentDto.getWriterName())
.password(commentDto.getPassword())
.content(commentDto.getContent())
.build()
);
}
}
2. 테스트

코드는 수정되었지만 테스트 코드 작성을 미리 해둔 덕분에 정상적으로 조회 및 저장된다는 것을 확인할 수 있다.
3. UML

SImple factory의 UML로 설명하자면 아래와 같이 대응된다.
client = CommentController
AbstractFactory = CommentSerivce
ConcreteFactoryX = CommentServiceBoardImpl
ConcreteFactoryY = CommentServiceDrinkImpl
Product = TypesRepository
ProductA = TypesBoardRepository
ProductB = TypesDrinkRepository
다음 포스팅에서는 팩토리 후기에 대해서 이야기해보겠다.
'개발' 카테고리의 다른 글
| Executing an update/delete query - 스케줄러에서 발생하는 예외가 API에서는 발생 했던 이유 (0) | 2025.11.12 |
|---|---|
| 디자인 패턴을 적용해보자 - 팩토리(4). (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 |