Effective Java 아이템 1. 생성자 대신 정적 팩토리 메소드를 고려하라

Jae·2024년 1월 21일

Effective Java

목록 보기
2/11

사내에서 인스턴스 생성을 어떻게 할 건지에 대해 얘기하다가 이전 회사에서 빌더를 이용한 것 보다 static factory method로 만들자고 했었던 거 때문에 생성자를 이용하거나 of 메서드를 이용한 것이 좋다고 주장했었는데 분명한 근거를 대지 못하던 차에 Effective Java 1장부터 그 내용이 나왔고 이해한 내용을 바탕으로 책을 정리해보기로 하였다.

인스턴스를 생성할 때, 생성자가 아닌 메서드를 이용해서 생성하자.

public static factory 메서드를 이용해서 인스턴스를 생성해서 반환하는 것이다.

장점1. 이름을 가질 수 있다.

생성자 자체는 인스턴스의 속성을 분명하게 알기 애매한 부분이 있다.

class Family {

  String mother;
  String father;
  String daughter;
  String son;
  
    public Family(String mother, String father, String daughter, String son) {
    this.mother = mother;
    this.father = father;
    this.daughter = daughter;
    this.son = son;
  }
}

위와 같이 생성자가 있을 때, (mother, father) 만 있다던지, daughter나 son를 추가하여 있는 경우 생성자의 경우 똑같은 타입을 파라미터로 받는 생성자를 두 개이상 만들 수 없기에 애매한 부분이 있다.

아래와 같이 static factory method를 이용해서 만들면 어떤 목적으로 인스턴스를 생성하는지 명시적으로 알 수 있다.

public static Family create(String mother, String father) {
  Family family = new Family();
  
  this.mother = mother;
  this.father = father;
  
  return family;
}

public static Family createWithDaughter(String mother, String father, String daughter) {
  Family family = new Family();
  
  this.mother = mother;
  this.father = father;
  this.daughter = daughter;
  
  return family;
}
}

장점2. 호출될 때마다 인스턴스를 새로 생성할 필요가 없다.

여러 번 호출되더라도 이미 생성된 동일 객체를 반환하기 때문에, 인스턴스의 존재를 직접 제어할 수 있다. 이러한 일을 하는 클래스를 인스턴스 제어 클래스라고 하는데, 인스턴스 제어 클래스는 싱글톤/ 인스턴스 생성불가 클래스로 만들 수 있고 관련된 내용은 3, 4장에서 학습 예정이다. 또한 불변클래스에서 동일 여부를 equals 가 아닌 == 으로도 가능해서 프로그램 성능도 향상될 수 있다고 하는데, equals로 하면 하나하나 비교고 == 주소값만으로도 비교되서 그런건가 싶다. 이 부분도 15장에서 알 수있다고 한다.

장점3. 자신이 반환하는 타입의 서브타입 객체도 반환 가능하다.

public interface List {
}

public class ArrayList implements List{
	public static List asList(int a)
	return new ArrayList(a);
}

위의 코드는 저런 경우가 생각이 안나서 만들어본건데, 대표적으로 java.util.Collection에서 static factory method를 이용해서 45개의 유틸리티 구현체를 제공한다.

장점4. 입력 매개변수에 따라 다른 클래스의 객체를 반환할 수 있다.

Chlid/ Adult가 Person을 상속받고 있다면 입력 변수에 따라 객체의 형태를 다양하게 반환받을 수 있다.

class Person {
  String name;

  public static Person newInstance(String name, int age) {
    if(age < 20 ) return new Child();
    return new Adult();
  }
}

단점1. static factory 메서드를 갖고 있고, public/protected 생성자가 없는 클래스는 서브클래스를 가질 수 없다.

그치만 이 부분은 상속 대신 컴포지션을 사용하도록 유도할 수 있기에 장점이 될 수도 있다.

단점2. 다른 static 메소드와 구별이 어렵다.

이게 인스턴스 생성하는 static인지 아닌지 구별이 어렵다는 의미로 이해된다. 생성자의 경우 Javadoc에서 자동으로 상단에 모아서 보여준다.

명명 컨벤션

단점 2를 보완하기 위해 메소드 명을 잘 지어야하는데 예시는 아래와 같다.

  • from
    하나의 매개변수를 받아서 객체를 생성할 때.
  • valueOf
    자신의 배개변수와 같은 값을 갖는 인스턴스를 반환한다. 줄여서 of 라고도 표현
  • getInstance
    매개변수에 나타난 인스턴스를 반환하지만, 매개변수와 같은 값을 갖지 않을 수도 있다. 이전의 인스턴스와 다른 인스턴스일 수 있다로 이해된다. (객체 실제 값은 같은데 내용이 다른?)
  • newInstance
    인스턴스가 새로 생성되는 경우
  • getINSTANCE_TYPE
    getInstance와 동일하지만, 팩토리 메서드가 다른 클래스에 있을 때 사용한다.
  • newINSTANCE_TYPE
    newInstance와 동일하지만, 팩토리 메서드가 다른 클래스에 있을 때 사용한다.

참고

effective java

0개의 댓글