티스토리 뷰
고전적으로 객체를 생성하는 방법에는 Public 생성자를 사용하는 방법이 있다.
하지만 이러한 방법 외에도 정적 팩토리 메서드를 제공하는 방법이 있다. 정적 팩터리 메서드란 해당 클래스의 객체를 반환해주는 단순한 메서드를 말한다.
여기서 이야기하려는 정적 팩토리 메서드는 디자인패턴에서 소개되는 팩토리 패턴과 다르다.
이러한 정적 팩터리 메서드의 장점에 대해서 살펴보자.
장점
1. 생성하는 메서드에 이름을 부여할 수 있다.
즉, Item(1, 2)와 같이 객체를 생성하는 것보다 Item.createWeapon(1, 2)와 같이 만드는게 객체 생성코드만으로 무엇을 하고자하는지 표현할 수 있다는 장점이 있다. 한 클래스에 동일한 시그니처를 가지는 생성자를 여러개 추가하는 것보다 정적 팩토리 메서드를 사용해 각각을 표현할 수 있는 메서드명을 지어주는게 좋다.
2. 호출될 때마다 인스턴스를 새로 생성하지 않아도 된다.
Immutable(불변) 클래스는 인스턴스를 미리 만들어 놓거나 새로 생성한 인스턴스를 캐싱하여 재활용하는 식으로 불필요한 객체 생성을 피할 수 있다.
이러한 클래스는 어떤 인스턴스를 언제 살아있을 수 있을지 철저하게 통제할 수 있다. 예를 들면 싱글톤 패턴으로 구성할 수도 있고 해당 클래스의 인스턴스를 만들지 못하도록 통제할 수도 있다.
3. 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.
이 방법은 클래스에 많은 유연성을 가져다 준다. 이 방법을 사용하면 구현 클래스를 공개하지 않고도 그 객체를 반환할 수 있어 API를 작게 유지할 수 있다. 즉, 인터페이스에 정적 메서드를 포함시켜(JAVA8 이후) 해당 인터페이스를 구현하는 여타 클래스들을 공개하지 않아도 이들의 객체를 반환할 수 있다는 말이다.
실제로 JAVA의 Collections(java.utils) 클래스(인터페이스는 아니지만 같은 맥락)는 인스턴스로 만들수 없는 클래스로 구현되어 있고, 정적 팩토리 메서드를 통해 Collection의 45개 클래스의 객체를 생성할 수 있다.
JAVA8 이후 인터페이스도 정적 메서드를 가질 수 있기 때문에 인스턴스화가 불가한 클래스를 그대로 둘 필요가 없어졌다. 클래스에 존재했던 다수의 정적 메서드들을 인터페이스에 포함시키면 되는 것이다.
4. 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
반환 타입의 하위 타입이기만 하면 어떤 클래스의 객체를 반환하든 상관없다. 심지어는 다른 클래스의 객체를 반환해도 된다.
EnumSet에는 사실 RegularEnumSet과 JumboEnumSet이 존재한다. OpenJDK에서는 원소의 개수에 따라서 둘 클래스중 하나의 객체를 반환하게 되는데, 클라이언트는 이 두 개의 클래스의 존재를 모른다.
public abstract class EnumSet { //EnumSet은 abstract하여 객체 생성이 불가능하다.
...
//noneOf 메소드에서 상황에 따라 다른 구현체 객체들을 만들어서 반환해주고 있다.
public static noneOf(...) {
if (enumElementSize <= 64)
return new RegularEnumSet<>(...);
else
return new JumboEnumSet<>(...);
}
}
5. 정적 팩토리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
이러한 유연함은 프레임워크를 개발하는데 도움이되고 가장 대표적인 예시로는 JDBC가 있다. (이 부분은 잘 이해가 안된다......)
단점
- 상속을 하려면 public이나 protected 생성자가 필요하니 정적 팩토리 메서드만 제공하면 하위 클래스를 만들 수 없다. 하지만, 상황에 따라서 오히려 상속을 불가능하게 만들 수 있다는 장점도 있다.
- 정적 팩토리 메서드는 프로그래머가 찾기 어렵다. 이 일을 자바 Docs에서 해결해주면 좋겠지만 항상 그럴수 없다는 한계가 존재하기 때문에 API 문서를 잘 쓰고 메서드 이름을 명확하게 제시하는 방향으로 해결해야 한다.
-> from, of, valueOf, instance, getInstance, create, newInstance, getType, newType, type과 같은 익히 알려진 메서드 이름을 사용하는것이 좋다.
핵심 정리
정적 팩토리 메서드와 public 생성자는 각각 쓰임새가 있기 때문에 어느 하나가 좋다고 말하긴 어렵다. 상황에 맞춰서 장단점을 비교해서 선택해 사용하면 된다. 하지만 정적 팩토리 메서드가 유리한 경우가 더 많기 때문에 항상 고려하자.
'개발 > Effective JAVA' 카테고리의 다른 글
[아이템9] try-finally보다는 try-with-resources를 사용하라 (0) | 2021.06.22 |
---|---|
[아이템7] 다 쓴 객체 참조를 해제하라 (0) | 2021.06.22 |
[아이템6] 불필요한 객체 생성을 피하라 (0) | 2021.06.20 |
[아이템4] 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2021.06.16 |
[아이템2] 생성자에 매개변수가 많다면 빌더를 고려하라 (0) | 2021.06.16 |