Contents
Effective-Java(Item1)
   Jun 27, 2022     3 min read

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;
    }

}