정적 팩토리 메서드

2023. 5. 23. 23:02JAVA

728x90

 

위 포스팅은 이팩티브 자바를 읽고 정적 팩토리 메서드에 대해서 정리한 글입니다.

 

이팩티브 자바

 

객체의 생성과 파괴

 

정적 팩토리 메서드를 보자마자 든 생각은 프로젝트에서 자주 사용하고 있는 내 코드이다.

public static Member createMember(String email, String mId, String password, String name){
        Member member = Member.builder()
                .email(email)
                .loginId(mId)
                .password(password)
                .name(name)
                .build();
        return member;
    }

 

위 코드에서는 정적 팩토리 메서드를 객체의 생성을 담당하는 역할로 사용하고 있다.

이번 포스팅에서는 위 방식으로 정적 팩토리 메서드를 사용하는 것이 옳은 방법인 것인가, 더 나은 방법은 없나에 대해서 생각해볼 예정이다.

 

객체를 생성하는 방법

 

클래스의 인스턴스를 얻을 수 있는 방법은 크게 2가지가 있다.

 

  1. public 생성자
  2. 정적 팩터리 메서드

public 생성자는 아마 프로그래밍을 좀 배워 본 사람이라면 알 것이다. 하지만, 정적 팩터리 메서드는 어떤 것일까??

 

 

정적 팩토리 메서드(Static Factory Method)란?

 

정적 팩토리 메서드는 객체 생성의 역할을 하는 클래스 메서드이다.

 

쉽게 말해서, 직접적으로 new를 사용해서 객체를 만들지 않고, 클래스 내에서 선언되어있는 메서드를 내부의 new를 이용해 객체를 생성해 반환하는 것이다.

 

다음은 String 클래스의 정적 팩터리 메서드이다.

@NotNull @Contract(pure = true)
public static String valueOf(@NotNull char data[]){
	return new String(data);
}

위 예시 코드에서처럼 객체를 직접 생성하는 것이 아닌 메서드를 통해 객체를 간접적으로 생성하는 것!

 

왜 정적 팩터리 메서드를 사용해야 할까?

 

이를 알기 위해서는 먼저 생성자와 정적 팩터리 메서드의 차이를 알아야한다.

일단, 정적 팩터리 메서드가 public 생성자보다 좋은 점은 아래와 같다.

 

1. 이름을 가질 수 있다.

BigInteger(int a, int b, Random c){}

BigInteger.probablePrime()

위 둘을 비교해보면, 값이 소수인 BigInteger를 반환한다 라는 의미를 정적 팩터리 메서드가 더 잘 전달한다.

   

 

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

 

public final class Boolean{
    
    public static final Boolean TRUE = new Boolean(true);
    public static final Boolean FALSE = new Boolean(false);

	public static Boolean valueOf(String s) {
        	return parseBoolean(s) ? TRUE : FALSE;
	}

}

위와 같이, 객체를 미리 생성해두고 객체를 사용한다면, 매번 새로운 객체를 생성할 필요가 없다.

 

 

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

 

예를 들어, Bike와 Car 클래스는 Movable 인터페이스를 구현합니다.

public interface Movable {
    public Movable move();
}

public class Bike implements Movable{
    @Override
    public Movable move() {
        return new Bike();
    }
}

public class Car implements Movable{
    @Override
    public Movable move() {
        return new Car();
    }
}

public class Test {

    public static Movable decide(int speed){
        if(speed > 80){
            return new Car();
        }else{
            return new Bike();
        }
    }

}

조건에 따라서, 하위 타입의 객체를 반환할 수 있다.

 

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

 public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
        Enum<?>[] universe = getUniverse(elementType);
        if (universe == null)
            throw new ClassCastException(elementType + " not an enum");

        if (universe.length <= 64)
            return new RegularEnumSet<>(elementType, universe);
        else
            return new JumboEnumSet<>(elementType, universe);
    }

 

EnumSet의 noneOf메서드는 enum의 원소의 수에따라서 구현체가 달라집니다.

 

기타 ) 

 

클래스에 정적 팩토리 메서드만 존재하는 클래스를 생성할 경우, 상속이 불가능하다는 특징이 있습니다.

또한, 정적 팩토리 메서드는 프로그래머가 찾기 어려우므로, 네이밍 컨벤션을 따르는 것이 사용할 때 편합니다.

 

네이밍 컨벤션


  • from : 하나의 매개 변수를 받아서 객체를 생성
  • of : 여러개의 매개 변수를 받아서 객체를 생성
  • getInstance | instance : 인스턴스를 생성. 이전에 반환했던 것과 같을 수 있음.
  • newInstance | create : 새로운 인스턴스를 생성

 

 

따라서, 정적 팩토리 메서드를 사용하는 경우는 객체의 형변환이 필요할 때, 여러 번의 객체 생성이 필요한 경우라면 정적 팩토리 메서드를 사용하는 것이 좋은 듯하다.

 

 

회고 : 첫 프로젝트때 정적 팩터리 메서드를 사용했었지만, 이게 무엇인 지 왜 사용하고 있었는 지 장단점은 무엇인지 모르고 사용했었다. 이번 기회를 통해서 정적 팩터리 메서드가 무엇이고 장단점은 어떤 것이고 언제 사용해야하는 지에대해서 알 수 있는 기회였다.

 

 

정적 팩토리 메서드(Static Factory Method)는 왜 사용할까?

 

정적 팩토리 메서드(Static Factory Method)는 왜 사용할까?

tecoble.techcourse.co.kr

 

728x90