정적 팩토리 메서드 (Static Factory Method)

Chooooo·2024년 7월 26일
0

TIL

목록 보기
27/28

😎 정적 팩토리 메서드 (Static Factory Method)

정의

정적 팩토리 메서드는 객체 생성을 캡슐화하는 static 메서드이다. 이 패턴은 생성자 대신 또는 생성자와 함께 사용되어 객체 생성 과정을 더 유연하게 의미있게 만든다.
-> 쉽게 말해 생성자로 인스턴스를 생성하지 않고, static Method를 사용해 인스턴스를 생성하는 방식

주요 특징

  1. 이름을 가질 수 있음 : 생성자와 달리 메서드 이름으로 생성 목적을 명확히 표현할 수 있다.
  2. 호출될 때마다 새로운 객체를 생성할 필요가 없음 : 캐싱 등을 통해 성능을 최적화할 수 있다.
  3. 반환 타입의 하위 타입 객체를 반환할 수 있음 : 인터페이스 기반 프레임워크 구현에 유용한다.
  4. 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있음: 유연한 객체 생성이 가능하다.
  5. 정적 팩토리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 됨: 서비스 제공자 프레임워크의 근간이 된다.

일반적인 정적 팩토리 메서드 명명 규칙

  • from: 하나의 매개변수를 받아 객체를 생성
  • of: 여러 매개변수를 받아 객체를 생성
  • valueOf: from과 of의 더 자세한 버전
  • instance 또는 getInstance: 싱글턴 인스턴스를 반환
  • create 또는 newInstance: 새로운 인스턴스를 생성
  • getType: 다른 타입의 인스턴스를 생성. Type은 반환할 객체의 타입
  • newType: 새로운 Type 인스턴스를 생성
  • type: getType과 newType의 간결한 버전

실무에서의 사용 : 정적 팩토리 메서드 + Builder 패턴

DTO에서의 사용

public class UserDTO {
    private String name;
    private String email;

    @Builder
    public UserDTO(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // DTO를 엔티티로 변환
    public User toEntity() {
        return User.builder()
                   .name(this.name)
                   .email(this.email)
                   .build();
    }

    // 엔티티로부터 DTO 생성
    public static UserDTO from(User user) {
        return UserDTO.builder()
                      .name(user.getName())
                      .email(user.getEmail())
                      .build();
    }
}

엔티티에서의 사용

@Entity
@Builder
@Getter
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    private String email;

    // 기본 생성자 (JPA 요구사항)
    protected User() {}

    // 모든 필드를 포함한 생성자
    @Builder
    public User(Long id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    // 특정 비즈니스 로직을 포함한 생성 메서드
    public static User createWithDefaultEmail(String name) {
        return User.builder()
                   .name(name)
                   .email(name.toLowerCase() + "@default.com")
                   .build();
    }
}
  • 위에서도 보듯이, 정적 팩토리 메서드의 주요 장점 중 하나는 메서드 이름을 통해 객체 생성 의도를 명확히 표현할 수 있다는 것.

DTO에서 자주 사용되는 정적 팩토리 메서드 이름과 용도

from

주로 다른 객체(주로 엔티티)로부터 DTO를 생성할 때 사용한다.

public static UserDTO from(User user) {
    return new UserDTO(user.getName(), user.getEmail());
}

of

여러 매개변수(여러 개의 객체)를 받아 DTO객체를 생성할 때 사용한다.

public static UserDTO of(String name, String email) {
    return new UserDTO(name, email);
}

to

DTO를 다른 타입(주로 엔티티)로 변환할 때 사용한다.

public User toEntity() {
    return new User(this.name, this.email);
}

create

새로운 DTO 인스턴스를 생성할 때 사용한다. 주로 복잡한 생성 로직이 필요할 때 사용.

public static UserDTO createWithDefaultEmail(String name) {
    return new UserDTO(name, name.toLowerCase() + "@default.com");
}

toResponse

DTO를 API 응답용 객체로 변환할 때 사용한다.

public UserResponse toResponse() {
    return new UserResponse(this.name, this.email);
}

fromRequest

API 요청 객체로부터 DTO를 생성할 때 사용

public static UserDTO fromRequest(CreateUserRequest request) {
    return new UserDTO(request.getName(), request.getEmail());
}

실무에서의 사용 예시

public class UserDTO {
    private String name;
    private String email;

    private UserDTO(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // Entity에서 DTO 생성
    public static UserDTO from(User user) {
        return new UserDTO(user.getName(), user.getEmail());
    }

    // 요청 객체에서 DTO 생성
    public static UserDTO fromRequest(CreateUserRequest request) {
        return new UserDTO(request.getName(), request.getEmail());
    }

    // DTO를 Entity로 변환
    public User toEntity() {
        return new User(this.name, this.email);
    }

    // DTO를 응답 객체로 변환
    public UserResponse toResponse() {
        return new UserResponse(this.name, this.email);
    }

    // 여러 매개변수로 DTO 생성
    public static UserDTO of(String name, String email) {
        return new UserDTO(name, email);
    }
}

이렇게 정적 팩토리 메서드를 사용하면 객체 생성의 의도를 명확히 하고, 코드의 가독성과 유지보수성을 높일 수 있다. 또한 각 메서드 내에서 필요한 유효성 검사나 추가적인 로직을 수행할 수 있어, 생성 과정을 더 잘 제어할 수 있다.

profile
back-end, 지속 성장 가능한 개발자를 향하여

0개의 댓글