What
정적 팩토리 메서드란?
- 클래스의 인스턴스를 반환하는 단순한 정적 메서드다.
- 클래스는 클라이언트에 public 생성자 외에도 정적 팩토리 메서드를 제공할 수 있다.
- 팩토리 메서드 디자인 패턴과는 전혀 관련 없는 개념이니 혼동하지 않도록 주의하자.
Why
장점 - 왜 사용하는가?
1. 이름을 가질 수 있다.
Human(String name, int height)
Human(String name, int weight) // 불가능, 위와 동일한 생성자 시그니처
Human(int weight, String name) // 가능, but 의미를 알 수 없음
- 동일한 시그니처로는 생성자를 단 하나만 만들 수 있다.
- 순서를 변경해 다른 시그니처로 만들 수 있지만, 개발자는 앞에오는 int 매개변수가 height인지 weight인지 기억할 수 없을 것이다. 설명 문서를 찾아보지 않고는 생성자의 의미를 알 수 없게 된다.
public static Human withHeight(String name, int height) {
Human human = new Human(name);
human.height = height;
return human;
}
public static Human withWeight(String name, int weight) {
Human human = new Human(name);
human.weight = weight;
return human;
}
- 반면 정적 팩토리 메서드는 매개변수의 순서와 타입이 같더라도 메서드 명을 다르게 정의할 수 있기 때문에 위와 같은 걱정을 할 필요가 사라진다.
- 또한 객체 생성의 의미가 분명하게 드러난다.
2. 인스턴스를 새로 생성하지 않아도 된다. (연관: Fly-weight 패턴)
public class OrderStatus {
private static final Map<String, OrderStatus> orderStatusMap = new HashMap<>();
private static final List<String> status = List.of("주문 접수", "조리 중", "배달 중", "배달 완료");
static {
status.forEach(s -> orderStatusMap.put(s, new OrderStatus(s)));
}
private String statusValue;
private OrderStatus() {}
private OrderStatus(String statusValue) {
this.statusValue = statusValue;
}
public static OrderStatus getInstance(String status) {
return orderStatusMap.get(status);
}
}
- 인스턴스를 미리 만들어 놓거나 새로 생성한 인스턴스를 캐싱해 재활용하는 방식으로 불필요한 객체 생성 비용을 줄일 수 있다.
- 싱글톤 객체로 만들거나, 인스턴스화가 불가능하게 막을 수 있다.
OrderStatus os1 = OrderStatus.getInstance("주문 접수");
OrderStatus os2 = OrderStatus.getInstance("주문 접수");
System.out.println(os1);
System.out.println(os2);
OrderStatus@3f0ee7cb
OrderStatus@3f0ee7cb
- 동치(
==
연산이 true)인 인스턴스가 단 하나뿐임을 보장할 수 있다.
3. 반환 타입의 하위 타입 객체를 반환할 수 있다.
4. 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
5. 정적 팩토리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
단점 - 왜 사용하기 불편한가?
1. 정적 팩토리 메서드만 제공하면 상속이 불가능하다.
- 정적 팩토리 메서드만 제공한다는 것은 생성자를 private으로 제공한다는 의미이다.
- 상속은 내부적으로 부모 클래스의 기본 생성자를 호출하는데, 접근이 불가능하므로 상속도 불가능하다.
2. 개발자가 정적 팩토리 메서드를 찾기 어려울 수 있다.
- 생성자의 경우 일반 메서드와 확실하게 구분이 가능하지만, 정적 팩토리 메서드의 경우 구분이 어려울 수 있다.
- 이럴 경우, 객체를 생성/반환할 때 정적 팩토리 메서드를 사용하도록 주석을 달거나 문서화를 제대로 해야 한다.
How
어떻게 사용하는가?
- 네이밍 컨벤션을 지켜 사용하자.
- from : 하나의 매개변수를 받아서 객체를 생성한다.
- of : 여러개의 매개변수를 받아서 객체를 생성한다.
- getInstance / instance : 인스턴스를 생성한다. 이전에 생성해둔 인스턴스를 반환할 수 있다.
- newInstance / create : 새로운 인스턴스를 생성한다.
- get[OtherType] : 다른 타입의 인스턴스를 생성한다. 이전에 생성해둔 인스턴스를 반환할 수 있다.
- new[OtherType] : 다른 타입의 새로운 인스턴스를 생성한다.
- public 생성자와 정적 팩토리 메서드 각자의 쓰임새에 따라 상대적 장단점을 이해하고 사용하자.
Reference
'개발 > Java' 카테고리의 다른 글
[Java] 자바 배열 원소를 이어 붙여서 출력하는 4가지 방법 (0) | 2024.05.31 |
---|---|
[Java] Map을 순회하는 3가지 방법 (0) | 2024.05.28 |
[Java] 자바 Optional 올바른 사용법 (0) | 2024.05.23 |
[Java] 자바 String 문자열, char 문자를 int 정수로 변환하기 (0) | 2024.05.21 |
[Java] 자바 객체 배열, 리스트 정렬하기 - Comparable vs. Comparator (0) | 2024.05.19 |