본문 바로가기
JAVA/effective-java

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

by saniii 2024. 5. 30.

 

클래스의 인스턴스를 얻는 전통적인 방법은 public 생성자를 사용하는 것이다. 하지만 이것 말고도 다른 방법이 하나 더 있다. 바로 정적 팩터리 메서드이다. 각자의 장단점을 잘 알고 상황에 알맞은 선택을 하자.

 

정적 팩토리 메서드, static factory method

▷ 클래스의 인스턴스를 반환하는 단순한 static method

public static Boolean valueOf (boolean b) {
	return b ? Boolean.TRUE : Boolean.FALSE;
}

 

정적 팩토리 메서드의 장점

1. 반환될 객체의 특성을 설명하는 이름을 가질 수 있다.

  • 생성자와 달리 정적 팩터리 메서드는 임의로 이름을 지을 수 있는데, 이런 특징을 살려 반환할 객체의 특성을 설명하는 이름을 지어 명시적인 코드를 작성할 수 있다.
  • 한 클래스 안에 시그니처가 같은 생성자가 여러 개 필요할 때 생성자를 정적 팩터리 메서드로 바꾸고 각각의 차이를 잘 드러내는 이름을 지어준다.

 

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

어쨌든 개발자가 만드는 메서드이기 때문에 내부적으로 인스턴스를 생성하여 반환하는 것이 아닌 원래 있던 인스턴스를 반환하는 등의 동작을 하도록 정의할 수 있다.

실제로 Boolean의 정적 팩토리 메서드인 valueOf는 인스턴스를 아예 생성하지 않는다.

  • (특히 생성 비용이 큰) 같은 객체가 자주 요청되는 상황에서는 성능을 상당히 끌어 올릴 수 있다.
  • 반복되는 요청에 같은 객체를 반환할 수 있는 정적 팩터리 방식의 클래스는 언제 어느 인스턴스를 살아있게 할지 통제할 수 있다. ( ⇒ 인스턴스 통제, instance-controlled )
    • 인스턴스를 통제하면 클래스를 싱글톤으로 만들수도, 인스턴스화 불가로 만들 수도 있으며 불변 값 클래스에서 동치인 인스턴스가 단 하나임을 보장할 수 있다.
  • 플라이웨이트 패턴, Flyweight Pattern
    • flyweight pattern은 만들어져있는 객체를 재사용하는 패턴으로 2번째 장점인 정적 팩터리 메서드를 이용하여 인스턴스를 통제할 수 있다는 2번째 장점이 잘 드러나 있다.
    • Integer의 valueOf, IntegerCache

자바의 Integer의 valueOf는 특정 범위(-128~127)안의 int i에 대해서 이미 만들어져있는 IntegerCache를 반환하고 이 범위를 벗어나는 int i 는 새로운 Integer 인스턴스를 생성하여 반환한다.

  • String의 string constant pool

 

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

  • 반환할 객체의 클래스를 자유롭게 선택할 수 있어 유연성이 높아진다. → 구현 클래스를 공개하지 않고도 객체를 반환할 수 있다.
  • Example : java.util.Collections
    • 자바의 컬렉션 프레임워크는 Collections의 정적 팩터리 메서드를 통해서 핵심 인터페이스에 동기화등의 기능을 덧붙인 유틸리티 여러 구현체를 제공한다.

Collections는 정적 메서드를 구현하기 위한 인터페이스 Collection의 동반 클래스로 인스턴스화가 불가능하도록 막아놓았다.

 

이렇게 제공하면 사용자 입장에서는 실제 구현 클래스가 어떤건지 알아야할 필요가 없어진다. 그저 정팩메를 통해 얻은 인스턴스를 인터페이스만으로 다룰 수 있다. 즉, API가 작아지고 API를 사용하기 위해서 알아야할 정보들이 줄어들게 되는 것이다.

 

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

  • Example: EnumSet의 정적 팩터리 메서드

 

사용자는 실제로 반환되는 RegularEnumSet과 JumboEnumSet을 몰라도 EnumSet을 사용할 수 있다. (두 클래스는 원소의 개수에 따라 관리하는 방법이 다르다. )

이렇게 가려놓으면 관리자 입장에서도 만약 원소 관리 방법을 바꾸고 싶을 때 다음 릴리스에서 변경해도 문제가 없다.

 

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

  • 이런 유연함은 service provider framework의 근간이 된다.

 

정적 팩토리 메서드의 단점

1. 상속을 하려면 public 이나 protected 생성자가 필요하기 때문에 정적 팩토리 메서드만 제공할 시 상속할 수 없다.

그렇지만 이 책을 더 읽다보면 상속은 지양하고 컴포지션을 권장하는데 이 단점은 오히려 이 책의 지향점으로 유도하기 때문에 장점이라고 볼 수도 있다.

 

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

생성자처럼 API 설명에 정확히 드러나지 않기 때문에 사용자가 찾아내야한다. 따라서 잘 알려진 명명 방식을 따름으로 문제를 완화하자.

from 매개변수를 하나 받아서 인스턴스 반환
of 매개변소를 여러개 받아서 인스턴스 반환
valueOf from과 of의 더 자세한 버전
instance 인스턴스 반환 (새로 만들 수도, 있던 걸 반환할 수도 있음)
create 매번 새로운 인스턴스 반환
getType B 클래스에 A 클래스의 정적 팩터리 메서드를 정의할 때 사용

 

 

정리하기

정적 팩터리 메서드와 public 생성자, 각자의 장단점을 잘 알고 상황에 알맞은 선택을 하쟈!

 

 

 


[ 참고 ]

https://m.yes24.com/Goods/Detail/65551284

 

이펙티브 자바 Effective Java 3/E - 예스24

자바 플랫폼 모범 사례 완벽 가이드 - Java 7, 8, 9 대응자바 6 출시 직후 출간된 『이펙티브 자바 2판』 이후로 자바는 커다란 변화를 겪었다. 그래서 졸트상에 빛나는 이 책도 자바 언어와 라이브

m.yes24.com

 

그리고... thanks to 약 500장의 책을 함께 끝낸 스터디원느님들......

댓글