본문 바로가기

개발

디자인 패턴을 적용해보자 - 팩토리(3). (pizza 예제 아님)

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

 

 

 

 

 

다음 포스팅에서는 팩토리 후기에 대해서 이야기해보겠다.