정적 팩토리 메서드

NNIIE·2022년 12월 7일
0

java

목록 보기
5/7
post-thumbnail
post-custom-banner

정적 팩토리 메소드


생성자 대신 정적 팩토리 메서드를 고려하라

// 정적 팩토리 메소드 ex
public class Person {

    private final String name;
    private final int age;

    private Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static Person of(String name, int age) {
        return new Person(name, age);
    }
}

클라이언트가 클래스의 인스턴스를 얻는 전통적인 수단은 public 생성자 이다.
하지만 클래스는 public 생성자와 대신 (혹은 생성자와 함께) 정적 팩터리 메서드를 제공할 수 있다.


장점

1. 이름을 가질 수 있다.

생성자에 넘기는 매개변수와 생성자 만으로는 반환될 객체의 특성을 제대로 파악하기 힘들다.
그러나 정적 팩터리는 네이밍이 가능함으로 반환될 객체의 특성을 쉽게 파악할 수 있다.

public class Car {

    private final String brand;

    private Car(String brand) {
        this.brand = brand;
    }

    public static Car brandFrom(String brand) {
        return new Car(brand);
    }
}

2. 호출될 때마다 인스턴스를 새로 생성하지 않을 수 있다.

불변클래스는 인스턴스를 미리 만들어 놓거나 새로 생성한 인스턴스를 캐싱하여 재활용하는 식으로
불필요한 객체 생성을 피할 수 있다.
enum과 같이 자주 사용되는 요소의 개수가 정해져있다면 해당 개수만큼 미리 생성해놓고
조회(캐싱)할 수 있는 구조로 만들수 있다.
정적 팩터리 메서드와 캐싱구조를 함께 사용하면 매번 새로운 객체를 생성할 필요가 없어진다.
즉, 객체 생성 비용이 큰 객체가 자주 생성된다면 성능상 이점을 볼 수 있다.

public class LottoNumber {
    
    private static final int MIN_LOTTO_NUMBER = 1;
    private static final int MAX_LOTTO_NUMBER = 45;

    private static Map<Integer, LottoNumber> lottoNumberCache = new HashMap<>();

    static {
        for (int i = MIN_LOTTO_NUMBER; i < MAX_LOTTO_NUMBER; i++) {
            lottoNumberCache.put(i, new LottoNumber(i));
        }
    }

    private int number;

    private LottoNumber(int number) {
        this.number = number;
    }

    public LottoNumber from(int number) {
        return lottoNumberCache.get(number);
    }
}

3. 하위 객체를 반환할 수 있다.

상속을 사용할 때 확인할 수 있다.
클라이언트에게 구현체를 노출하지 않고 반환할 수 있고 결국 API의 개념적 무게가 가벼워 진다.

public static Grade of(int score) {
    if (score < 70) {
        return new Fail;
    }
    if (score > 70) {
        return new Pass;
    }
}
class Fail extends Grade {}
class Pass extends Grade {}

단점

1. 상속문제

인스턴스 통제 클래스를 구현하기 위해서는 new 키워드를 사용하여 임의로 객체를 생성함을 막아야한다.
이를 위해 생성자의 접근 제어자를 private 로 설정해야하는데, 생성자가 private 인 클래스는 상속을 할 수 없다. 즉, 부모 클래스가 될 수 없다.
이 제약은 컴포지션을 사용하도록 유도하고 불변타입으로 만들려면 이 제약을 지켜야 한다는 점에서 오히려 장점으로 받아들여 진다.

2. 정적 팩터리 메서드는 프로그래머가 찾기 어렵다.

네이밍 컨벤션

  • from : 하나의 매개 변수를 받아서 객체를 생성
  • of : 여러개의 매개 변수를 받아서 객체를 생성
  • getInstance & instance : 인스턴스를 생성. 이전에 반환했던 것과 같을 수 있음.
  • newInstance & create : 새로운 인스턴스를 생성
  • get[OtherType] : 다른 타입의 인스턴스를 생성. 이전에 반환했던 것과 같을 수 있음.
  • new[OtherType] : 다른 타입의 새로운 인스턴스를 생성.
post-custom-banner

0개의 댓글