정적 팩토리 메서드와 빌더 패턴
정적 팩토리 메서드
조슈아 블로크의 저서 “이펙티브 자바”에서는 생성자 대신 정적 팩토리 메서드를 고려하라!라고 한다.
생성자와 정적 팩토리 메서드는 객체를 생성한다는 같은 역할을 하고 있지만 그 활용도는 엄연히 차이가 난다
웹 어플리케이션을 개발하다보면 계층 간에 데이터를 전송하기 위한 객체로 DTO(Data transfer object)를 정의해서 사용한다.
public class CarDto {
private String name;
private int position;
pulbic static CarDto from(Car car) {
return new CarDto(car.getName(), car.getPosition());
}
}
DTO와 Entity간에는 자유롭게 형 변환이 가능해야 하는데,
정적 팩터리 메서드를 사용하면 내부 구현을 모르더라도 쉽게 변환할 수 있다.
// Car -> CatDto 로 변환
CarDto carDto = CarDto.from(car);
만약, 정적 팩토리 메서드를 쓰지 않고 DTO로 변환한다면
외부에서 생성자의 내부 구현을 모두 드러내야 한다.
Car carDto = CarDto.from(car); // 정적 팩토리 메서드를 쓴 경우
CarDto carDto = new CarDto(car.getName(), car.getPosition); // 생성자를 쓴 경우
빌더 패턴과 정적 팩토리 메서드
** 정적 팩토리 메서드 사용이 좋은 경우
매개변수가 적을 때 (2~3개 이하)
객체 생성 로직이 복잡하거나 캐싱이 필요할 때
상황에 따라 다른 객체를 반환해야 할 때
** 빌더 패턴 사용이 좋은 경우
매개변수가 많을 때 (4개 이상)
선택적 매개변수가 많을 때
불변 객체를 생성해야 할 때
객체 생성에 여러 단계가 필요할 때
[정리]
DTO나 간단한 객체는 정적 팩토리 메서드
도메인 객체나 복잡한 객체는 빌더 패턴를 사용하자.
일반적인 정적 팩토리 메서드 명명 규칙
public class Order {
// from: 다른 객체로부터 인스턴스 생성
public static Order from(OrderRequest request) {
return new Order(request.getCustomerId(), request.getItems());
}
// of: 여러 매개변수로부터 인스턴스 생성
public static Order of(String customerId, List<OrderItem> items) {
return new Order(customerId, items);
}
// create: 새로운 인스턴스 생성
public static Order createEmpty() {
return new Order(null, new ArrayList<>());
}
// valueOf: 상세한 버전
public static Order valueOf(Map<String, Object> orderMap) {
return new Order(
(String) orderMap.get("customerId"),
(List<OrderItem>) orderMap.get("items")
);
}
}