Effective-Java(Item1)
Item 1. 생성자 대신 정적 팩터리 메서드를 고려하라
정적팩토리 메소드의 장점
1.이름을 가질 수 있다. (동일한 시그니처의 생성자를 두 개 가질 수 없다.)
이름을 가질 수 있다는 말은 표현을 내가 직접 할 수 있다는 뜻이다. Order클래스의 생성자는 Order의 이름을 갖고 있어야하지만 정적팩토리 메소드를 사용할 경우 내가 직접 표현할 수 있다는 뜻.
상황 : 아래와 같이 있던 상황 중 urgent Order를 추가하고 싶을 때 , prime Order와 urgent Order 분리해서 생성자를 하고 싶다. 어떻게 해야할까 ?
public class Order {
private boolean prime;
private Product product;
public Order(Product product, boolean prime){
this.product = product;
this.prime = prime;
}
}
생성자 타입이 동일한 경우
// 생성자 2개 사용 할 때
public class Order {
private boolean prime;
private boolean urgent;
private Product product;
public Order(Product product, boolean prime) {
this.product = product;
this.prime = prime;
}
public Order(Product product, boolean urgent) {
this.product = product;
this.urgent = urgent;
}
}
위와 같이 생성자를 사용할 경우
Order(Product, boolean)’ is already defined in ‘me.chapter01.item01.Order’ ← 이런 에러가 뜬다.
이유는 같은 타입에 인스턴스를 리턴해주는 생성자의 시그니쳐가 파라미터의 타입까지 보는데, 타입(Product, boolean)이 같으면 매개변수 이름이 다르더라도 상관없이 동일하다고 보기때문에 에러가 난다.
// 순서바꾸기를 이용한 에러 우회하기
public Order(Product product, boolean prime) {}
public Order(boolean urgent, Product product) {}
매개변수의 순서를 바꿔준다. 하지만 생성자는 클래스의 이름과 같아야 하기때문에 prime Order인지 ? urgent Order인지 구별하기 어렵다.
인자의 수를 늘리는 방법
// 인자수를 하나 더 늘려서 하는 방법
public Order(Product product, boolean prime) {}
public Order(boolean urgent, Product product, boolean prime) {}
생성자는 한 종류의 시그니쳐만 있어야한다. 그래서 위 처럼 가능하다. 하지만 잘 사용 안하는 듯 하다.
해결 방법 : 정적 팩토리 메서드를 사용하자!
생성자 대신 정적 팩토리 메서드 사용
- primeOrder 메서드 라는 이름을 사용해서 만들 수 있다.
public static Order primeOrder(Product product) {
Order order = new Order();
order.prime = true;
order.product = product;
return order;
}
- urgentOrder 메서드 라는 이름을 사용해서 만들 수 있다.
public static Order urgentOrder(Product product){
Order order = new Order();
order.urgent = true;
order.product = product;
return order;
}
- 완성된 코드
public class Order {
private boolean prime;
private boolean urgent;
private Product product;
//public Order(){} // 기본생성자는 코드로 작성을 안해도 디폴트로 있다. 그래서 생략 가능
public static Order primeOrder(Product product) {
Order order = new Order();
order.prime = true;
order.product = product;
return order;
}
public static Order urgentOrder(Product product){
Order order = new Order();
order.urgent = true;
order.product = product;
return order;
}
}