정적 팩토리 메소드의 특징
정적 팩토리 메소드의 장점은 곧 특징이 돼요. 크게 4가지의 장점이 있어요.
장점
이름이 있으므로 생성자에 비해 가독성이 좋다.
호출할 때마다 새로운 객체를 생성할 필요가 없다.
하위 자료형 객체를 반환할 수 있다.
형인자 자료형 객체를 만들 때 편리하다.
단점으로는 2가지가 있는데요.
단점
정적 팩토리 메서드만 있는 클래스라면, 생성자가 없으므로 하위 클래스를 못 만든다.
정적 팩토리 메서드는 다른 정적 메서드와 잘 구분되지 않는다. (문서만으로 확인하기 어려울 수 있음)
장, 단점을 알면, 이제 도대체 언제 써야하는지 알아야겠죠? 그전에 매번 헷갈리는 정적 팩토리 메소드의 네이밍 컨벤션
을 조금 살펴보고 가야할거 같아요.
정적 팩토리 메소드 네이밍 컨벤션
from
: 하나의 매개변수를 받아 해당 타입의 인스턴스를 반환Number number = Number.from(instant);
of
: 여러개의 매개변수를 받아 적합한 타입의 인스턴스를 반환이번 미션 코드에서 사용한다면,
package java.util; public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> implements Cloneable, Serializable { ... public static <E extends Enum<E>> EnumSet<E> of(E var0, E var1, E var2) { EnumSet var3 = noneOf(var0.getDeclaringClass()); var3.add(var0); var3.add(var1); var3.add(var2); return var3; } ... } public enum Number { ... ACE("A", 11, 1), TWO("2", 2), THREE("3", 3), ... } public static void main(String[] args) { EnumSet<Number> numberSet = EnumSet.of(Number.ACE, Number.TWO, Number.THREE); }
valueOf
:from과 of
의 조금더 자세한 버전package java.math; public class BigDecimal extends Number implements Comparable<BigDecimal> { ... public static BigDecimal valueOf(long val) { if (val >= 0 && val < zeroThroughTen.length) return zeroThroughTen[(int)val]; else if (val != INFLATED) return new BigDecimal(null, val, 0, 0); return new BigDecimal(INFLATED_BIGINT, val, 0, 0); } ... } public static void main(String[] args) { BigDecimal lucky = BigDeciaml.valueOf(777); }
instance,
getInstance
: (매개변수를 받는다면) 매개변수로 명시한 인스턴스를 반환하지만, 같은(equals) 인스턴스임을 보장하지 않음. 즉 , 매개변수와 같은 값을 갖지 않을 수도 있다.package java.util; public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> { ... public static Calendar getInstance(TimeZone zone) { return createCalendar(zone, Locale.getDefault(Locale.Category.FORMAT)); } ... } public static void main(String[] args) { Calendar instance = Calendar.getInstance(Locale.KOREA); }
create or newInstance
: getInstance와 같지만 호출 시 매번 다른 객체를 반환한다.getXxxx
: getInstance와 같으나 호출하는 클래스와 다른 타입의 인스턴스를 반환할때 사용- 예를들어 Date.getInstance() 는 Date 타입의 인스턴스를 반환하지만 Date와 상관없는 Period 타입을 반환한다면 Date.getPeriod() 가 된다.
newXxxx
: getXxxx와 같으나 매번 새로운 인스턴스를 반환한다. newInstance와 같지만 반환될 객체의 클래스와 다른 클래스에 팩토리 메소드가 있을 때 사용한다. Type은 팩토리 메소드가 반환할 객체의 자료형.
내가 생각하는 사용시기
주 생성자, 부생성자로도 충분하다.
다만 생성의 의미를 더 정확하게 할 수 있다면 정적 팩토리 메소드를 써도 괜찮을듯..!
private static final Map<Integer, LottoBall> lottoBalls = new HashMap<>();
static {
for (int i = MIN_LOTTO_VALUE; i <= MAX_LOTTO_VALUE; i++) {
lottoBalls.put(i, new LottoBall(i));
}
}
private final int value;
private LottoBall(final int value) {
this.value = value;
}
public static LottoBall from(final int value) {
if (Objects.isNull(lottoBalls.get(value))) {
throw new IllegalArgumentException(String.format(PERMIT_LOTTO_NUMBER_EXCEPTION_MESSAGE, MIN_LOTTO_VALUE, MAX_LOTTO_VALUE));
}
return lottoBalls.get(value);
}
댓글