자바(JAVA) - 팩토리 메소드 패턴(Factory Method Pattern)
팩토리 메소드 패턴은 제 블로그에 정리되어있습니다.
로그인에 접근하는 외부 API는 언제든지 변경될 수 있습니다. 작성기준 현재 소셜로그인은 카카오 API만 존재합니다. 하지만 이후에 네이버, 깃, 구글 등 여러 외부 API로 연동한다고하면 검증부터 구현까지 다시 만들어야하는 불편함이 있습니다. 또한 로그인 로직에 대한 일관성도 깨질 수 있는만큼 확장성을 생각하여 디자인패턴 - 생성패턴에 팩토리 메소드 패턴을 구현했습니다.
public interface MemberFactory {
MemberInterface createMember();
MemberValidator validator();
@Transactional
default Member signup(RequestSignupDto signupDto) {
MemberInterface memberInterface = createMember();
MemberValidator validator = validator();
validator.validSignup(signupDto);
return memberInterface.signup(signupDto);
}
@Transactional
default Member login(RequestLoginDto loginDto, HttpSession session, HttpServletResponse response) {
MemberInterface memberInterface = createMember();
Member member = memberInterface.login(loginDto);
MemberValidator validator = validator();
validator.validLogin(member, response);
if (member != null) {
session.setAttribute(LOGIN_MEMBER, member.getMemberId());
}
return member;
}
}
팩토리 인터페이스를 구현하고 createMember와 validator를 구현체에 오버라이드 시킵니다.
그리고 실제 로그인과 회원가입 로직을 인터페이스의 default 로 구현하여 모든 외부 API와 일반로직을 통합시킵니다.
따라서 createMember와 validator를 하위 구현체에서 구현하기만 하면 현재 코드에 손대지 않고 손쉽게 외부 API를 확장할 수 있습니다.
즉 수정에는 닫혀있고, 확장에는 열려있는 OCP원칙을 지킬 수 있고, 각 API에 대한 구현체가 생성되기 때문에 단일책임원칙도 지킬 수 있게 되었습니다.
@RequiredArgsConstructor
public class DefaultMemberFactory implements MemberFactory{
private final BasicJpaRepository basicJpaRepository;
private final MemberJpaRepository memberJpaRepository;
private final FreezeRepository freezeRepository;
private final BCryptPasswordEncoder encoder;
@Override
public MemberInterface createMember() {
return new DefaultMember(basicJpaRepository, memberJpaRepository, encoder);
}
@Override
public MemberValidator validator() {
return new DefaultMemberValidator(freezeRepository, basicJpaRepository, memberJpaRepository);
}
}
@RequiredArgsConstructor
public class KakaoMemberFactory implements MemberFactory{
private final FreezeRepository freezeRepository;
private final KakaoLoginRepository kakaoLoginRepository;
private final MemberJpaRepository memberJpaRepository;
private final SocialJpaRepository socialJpaRepository;
private final SocialTokenJpaRepository socialTokenJpaRepository;
private final PhoneJpaRepository phoneJpaRepository;
@Override
public MemberInterface createMember() {
return new KakaoMember(kakaoLoginRepository, memberJpaRepository, socialJpaRepository, socialTokenJpaRepository, phoneJpaRepository);
}
@Override
public MemberValidator validator() {
return new SocialMemberValidator(freezeRepository, socialJpaRepository, memberJpaRepository);
}
}