반응형
이펙티브 자바(Effective java) 를 읽고 정리한 글입니다.
클래스는 생성자와 별도로 정적 팩터리 메서드(static factory method)를 제공할 수 있다.
정적 팩터리 메서드는 단순히 클래스의 인스턴스를 반환하는 정적 메서드이다.
그 예시로 우리가 자주 사용하는 boolean 타입 의 박싱 클래스인 Boolean 의 일부 코드를 보면 쉽게 이해할 수 있다.
public static Boolean value0f(boolean b) {
return b ? Boolean. TRUE : Boolean. FALSE;
}
그럼 이제 정적 팩터리 메서드는 어떤 특징을 가지는지 알아보자.
장점
정적 팩터리 메서드의 장점은 아래와 같다.
1. 이름을 가질 수 있다.
- 생성자는 그 자체만으로 반환될 객체의 특성을 설명하기 어렵다.
→ 정적 팩터리는 이름을 가지기 때문에, 이름으로 객체의 특성을 묘사할 수 있다. - 하나의 시그니처로는 생성자를 하나만 만들 수 있다.
→ 정적 팩터리는 이러한 제약이 없다. 이름이 다르니 시그니처가 같아도 문제 없다.
2. 호출될 때마다 인스턴스를 새로 생성하지는 않아도 된다.
- 이러한 특성으로, 불변 클래스는 인스턴스를 미리 만들어 놓거나, 재활용 할 수 있다 (플라이웨이트 패턴과 유사).
→ 불필요한 객체 생성을 하지 않아도 된다. - 언제 어느 인스턴스를 살아 있게 할지를 철저히 통제할 수 있다 (인스턴스 통제 클래스).
→ 인스턴스를 통제하면 싱글턴으로 만들 수도, 인스턴스화 불가로 만들 수도 있다.
→ 불변 값 클래스에서 동치인 인스턴스가 하나뿐임을 보장할 수 있음
3. 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.
- 이 특성으로 객체는 엄청난 유연성을 가진다.
- 구현 클래스를 공개하지 않고도 그 객체를 반환할 수 있다.
→ API를 작게 유지할 수 있다.
→ 클라이언트는 정적 팩터리 메서드로 얻은 객체를 인터페이스만으로 다룰 수 있음
→ 예시 : Collections API
4. 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
- 클라이언트는 정적 팩터리가 반환하는 객체가 어느 클래스의 인스턴스인지 알 필요가 없다.
→ 예시 : EnumSet
5. 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
- 이 특징은 서비스 제공자 프레임워크(service provider framework)를 만드는 근간이 된다.
→ 예시 : JDBC - 클라이언트는 서비스 접근 API를 사용할 때 원하는 구현체 명시 가능
참고로 서비스 제공자 프레임워크는 3개의 핵심 컴포넌트로 이뤄진다.
1. 서비스 인터페이스 (service interface): 구현체의 동작을 정의
2. 제공자 등록 API (provider registration API): 제공자가 구현체를 등록할 때 사용
3. 서비스 접근 API (service access API): 클라이언트가 서비스의 인스턴스를 얻을 때 사용
+ 서비스 제공자 인터페이스 (service provider interface) : 서비스 인터페이스의 인스턴스를 생성하는 팩터리 객체를 설명
단점
정적 팩터리 메서드의 단점은 아래와 같다.
1. 상속을 하려면 public 이나 protected 생성자가 필요하니 정적 팩터리 메서드만 제공하면 하위 클래스를 만들 수 없다.
- 하지만 상속보다 컴포지션을 사용하도록 유도하고, 불변 타입을 만드는 관점에서 오히려 장점일 수 있다.
2. 정적 팩터리 메서드는 프로그래머가 찾기 어렵다.
- 생성자처럼 API 설명에 명확히 드러나지 않는다.
- 이러한 단점을 보완하기 위해 일반적으로 알려진 명명 방식(규약)을 따르는 것이 좋다.
일반적인 정적 팩터리 메서드 명명 방식
메서드명 | 의미 |
from | 매개변수를 하나 받아서 해당 타입의 인스턴스를 반환하는 형변환 메서드 |
of | 여러 매개변수를 받아 적합한 타입의 인스턴스를 반환하는 집계 메서드 |
valueOf | from과 of의 더 자세한 버전 |
instance, getInstance | 매개변수로 명시한 인스턴스를 반환하지만, 같은 인스턴스임을 보장하지는 않음 |
create, newInstance | 매개변수로 명시한 인스턴스를 반환하며, 매번 새로운 인스턴스를 생성해 반환함을 보장 |
getType | getInstance와 같으나, 생성할 클래스가 아닌 다른 클래스에 팩터리 메서드를 정의할 때 사용. "Type"은 메서드가 반환할 객체의 타입 예시: FileStore fs = Files.getFileStore(path) |
newType | newInstance와 같으나, 생성할 클래스가 아닌 다른 클래스에 팩터리 메서드를 정의할 때 사용. "Type"은 메서드가 반환할 객체의 타입 예시: BufferedReader br = Files.newBufferedReader(path); |
type | getType, newType의 간결한 버전 |
요약
정적 팩터리 메서드, public 생성자의 장단점을 알고 사용하자.
반응형
'프로그래밍 언어 > Java' 카테고리의 다른 글
이펙티브 자바 - 아이템 6. 불필요한 객체 생성을 피하라 (0) | 2024.08.20 |
---|---|
이펙티브 자바 - 아이템 5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) | 2024.08.20 |
이펙티브 자바 - 아이템 4. 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2024.08.17 |
이펙티브 자바 - 아이템3. private 생성자나 열거 타입으로 싱글턴임을 보증하라. (2) | 2024.08.14 |
이펙티브 자바 - 아이템2. 생성자에 매개변수가 많다면 빌더를 고려하라 (0) | 2024.08.13 |