정적 펙토리 메소드

스프링을 공부하던 중 메서드명이 “of“로 선언된 케이스를 많이 보았고 뭔가 특정상황에 사용되는 느낌을 받았다.

image

그리하여 오픈톡방에 물어보니 위와 같은 답변을 받았다. 정적 팩토리 메소드가 무엇일까..?

정적 팩토리 메소드

핵심만 말하면 객체의 생성의 역할을 하는 클래스 메서드 이다.

일반적으로 객체를 생성하기 위해서는 new라는 키워드를 사용한다.

정적 팩토리 메소드는 new를 직접적으로 사용하지 않고 메서드 내부의 new를 이용해 객체를 생성하는 것이다.

코드 예시

image

위에서 보면 알 수 있듯이 Optional Of()는 파라미터로 값을 받으면, 그 값을 기반으로 Optional 객체를 반환해준다.

생성자(new)와는 어떤 차이가 있을까?

이펙티브 자바라는 책에는 정적 팩토리 메서드에는 5가지의 다른 점이 있다고 한다.

  1. 이름을 가질 수 있다.
  2. 호출 될 때 마다 인스턴스를 새로 생성하지 않아도 된다.
  3. 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.
  4. 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
  5. 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.

(직관적으로 이해가 가는 것만 설명해보겠다.)

1. 이름을 가질 수 있다.

메서드 네이밍에 따라 코드의 가독성이 상승 할 수 있다는 장점이 있다.

아래와 같은 Car class가 있다고 하자

public class Car {

    private final String name;
    private final int oil;

   }

생성자 ver

public class Car {

    private final String name;
    private final int oil;

    public Car(String name, int oil) {
        this.name = name;
        this.oil = oil;
    }
    
    public Car(String name){
        this.name = name;
        this.oil = 0;
    }
}

정적 팩토리 메서드 ver

public class Car {

    private final String name;
    private final int oil;

    public static Car createCar(String name, int oil) {
        return new Car(name, oil);
    }

    public static Car createNoOilCar(String name) {
        return new Car(name, 0);
    }

    private Car(String name, int oil) {
        this.name = name;
        this.oil = oil;
    }
}

2. 호출 될 때 마다 인스턴스를 새로 생성하지 않아도 된다

(이부분은 잘 이해가 안된다. 추후에 공부 후 추가해보겠다.)

3. 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다

상속을 사용하는 경우 확인해 볼 수 있다. 이는 생성자의 역할을 하는 정적 팩토리 메서드가 반환값을 가지고 있기 때문에 가능하다.

public class Level {
  ...
  public static Level of(int score) {
    if (score < 50) {
      return new Basic();
    } else if (score < 80) {
      return new Intermediate();
    } else {
      return new Advanced();
    }
  }
  ...
}

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

위에서 언급했던 Car 클래스의 정적메소드펙토리를 예시로 들면 알 수 있다.

public class Car {

    private final String name;
    private final int oil;

    public static Car createCar(String name, int oil) {
        return new Car(name, oil);
    }

    public static Car createNoOilCar(String name) {
        return new Car(name, 0);
    }

    private Car(String name, int oil) {
        this.name = name;
        this.oil = oil;
    }
}

(부가적으로 말하면 객체 생성을 캡슐화 할 수 있다.)

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

(이 부분도 추가적으로 공부를 진행한 후 보충하겠다.)

정적 팩토리 메서드 명명방식

정적 메서드 네이밍 컨벤션에는 아래와 같은 경우가 있다.

  • of : 여러 매개변수를 받아 적합한 타입의 인스턴스를 반환하는 집계 메서드
  • from : 하나의 매개변수를 받아 해당 타입의 인스턴스를 반환하는 형변환 메서드
  • instance 혹은 getInstance : 매개변수로 명시한 인스턴스를 반환하지만, 같은 인스턴스임을 보장 하지 않음
  • create 혹은 newInstance :instance 혹은 getInstance 와 같으나 매번 새로운 인스턴스를 생성해 반환 함을 보장.
  • get[OtherType] : 다른 타입의 인스턴스를 생성. 이전에 반환했던 것과 같을 수 있음.
  • new[OtherType] : 다른 타입의 새로운 인스턴스를 생성.

Categories:

Updated:

Leave a comment