https://inpa.tistory.com/entry/GOF-💠-정적-팩토리-메서드-생성자-대신-사용하자

Static Factory Method(정적 메소드)

public 생성자를 사용해 객체를 생성하는 방법 외 다음과 같이 public static factory method 를 사용해 해당 클래스의 인스턴스를 만드는 방법이 있음

// boolean의 기본 타입의 값을 받아 Boolean 객체 참조로 변환
public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

이처럼 생성자 대신 정적 팩토리 메소드를 사용하는 것에 대한 장단점은 다음과 같음

장점

  1. 이름을 가질 수 있음

    public class Book {
        private String title;
        private String author;
    
        // 생성자1
        public Book(String title, String author){
            this.title = title;
            this.author = author;
        }
    
        /**
         * 생성자는 하나의 시그니처만 사용하므로, 다음과 같이 생성자 생성이 불가능하다.
         *
         */
        public Book(String title){
            this.title = title;
        }
    
        public Book(String author){
            this.author = author;
        }
    }
    

    생성자는 똑같은 타입의 파라미터로 받는 생성자를 여러개 생성할 수 없음

    static factory method는 한 클래스에 시그니처가 같은 생성자가 여러 개 필요한 경우에도 사용할 수 있으며, 또한, 파라미터가 반환하는 객체를 잘 설명하지 못하는 경우에, 이름을 잘 지은 static factory method를 사용할 수 있음

    public class Book {
      String title;
      String author;
    
      public Book(String title, String author){
        this.title = title;
        this.autor = author;
      }
    
      public Book(){}
    
      /*
      * withName, withTitle과 같이 이름을 명시적으로 선언할 수 있으며,
      * 한 클래스에 시그니처가 같은(String) 생성자가 여러개 필요한 경우에도 다음과 같이 생성할 수 있다.
      */
    
      public static Book withAuthor(String author){
        Book book = new Book();
        book.author = author;
        return book;
      }
    
      public static Book withTitle(String title){
        Book book = new Book();
        book.title = title;
        return book;
      }
    }
    
  2. 호출될 때마다 인스턴스를 새로 생성하지 않아도 됨

    public final class Boolean implements java.io.Serializable,
                                          Comparable<Boolean>
    {
        /**
         * The {@code Boolean} object corresponding to the primitive
         * value {@code true}.
         */
        public static final Boolean TRUE = new Boolean(true);
    
        /**
         * The {@code Boolean} object corresponding to the primitive
         * value {@code false}.
         */
        public static final Boolean FALSE = new Boolean(false);
             // ...
    }
    
    // boolean의 기본 타입의 값을 받아 Boolean 객체 참조로 변환
    public static Boolean valueOf(boolean b){
        return b ? Boolean.TRUE : Boolean.FALSE;
    }
    
  3. 리턴 타입의 하위 타입 객체를 반환할 수 있음

    // java7 Collections.emptyList()
    public Collections(){
          ///...
    
        public static final List EMPTY_LIST = new EmptyList<>();
    
        public static final <T> List<T> emptyList() {
            return (List<T>) EMPTY_LIST;
        }
    
          //...
    }
    
    // java9 List of()
    static <E> List<E> of() {
        return (List<E>) ImmutableCollections.ListN.EMPTY_LIST;
    }
    
  4. 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있음

  5. 정적 팩토리 메소드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 됨