728x90
SMALL
목적
객체 생성을 생각하면 나는 보통 public 생성자를 떠올린다.
클라이언트에서 객체 생성을 할 때, public 생성자를 이용한 방법이 아닌
정적 팩터리 메서드를 이용한 방법을 알아보자.
- 정적 팩터리 메서드에 대해서 알아보자
- 정적 팩터리 메서드의 장단점에 대해 알아보자
- 책을 읽고 정리하자
정적 팩터리 메서드
클래스의 인스턴스를 반환하는 단순한 정적 메서드
예시
boolean의 값을 받아 Boolean 객체 참조로 변환하는 코드public static Boolean valueOf(boolean b) { return (b ? TRUE : FALSE); }
장점
- 1. 이름을 가질 수 있다.
- 반환될 객체의 특성을 쉽게 묘사 가능
- 💡 임의의 소수 값 BigInteger 반환
BigInteger(int,int,Random)
보다BigInteger.probablePrime
이 의미가 더 명확
- 💡 임의의 소수 값 BigInteger 반환
- 생성자는 역할을 기억하기 어려움
- 반환될 객체의 특성을 쉽게 묘사 가능
- 2.호출마다 인스턴스 생성이 필요없다.
- 불필요한 객체 생성을 피할 수 있다.
- 같은 객체가 자주 요청되는 상황에서 유용하다.
- 인스턴스 통제(instance-controlled) 클래스로 만들 수 있다.
- 정적 팩터리 방식의 클래스는 언제 어느 인스턴스를 살아 있게 할지를 통제 가능하다.
- 💡 인스턴스를 통제로 가능한 일
- 싱글턴
- 인스턴스화 방지
- 동치인 인스턴스가 단 하나뿐임을 보장(
a==b
→a.equals(b)
)
- 3. 반환 타입의 하위 타입 객체를 반환할 수 있다.
- 반환할 객체의 클래스 선택이 가능하다 → 유연성 증가
- 구현 클래스 공개가 필수가 아니다. → API 작게 유지 가능
💡 인터페이스 기반 프레임워크를 만들 수 있다.
인터페이스를 정적 펙터리 메서드의 반환 타입으로 사용
자바 8 이전에는 인터페이스에 정적 메서드 선언이 불가해서 (인스턴스화 불가인) 동반 클래스를 만들어 정의 했다고 한다.
예시 중 하나가 Collections 다.
Collections
클래스는 자주 사용되는 정적 메소드(static methods)를 제공하는 유틸리티 클래스다.객체 생성 없이 바로 접근 가능하며 유틸리티성 함수와 상수값들을 제공한다.
public static final <T> List<T> emptyList() { return (List<T>) EMPTY_LIST; }// public static final List EMPTY_LIST = new EmptyList<>();
// 비어있는 리스트 구현체를 반환 List<String> emptyList = Collections.emptyList();
- 4. 입력 매개변수에 따라 매번 다른 클래스(반환타입의 하위타입)의 객체를 반환 가능
- 아래 코드는 원소가
- 64개 이하면
RegularEnumSet
(원소들을 long 변수 하나로 관리) - 65개 이상이면
JumboEnumSet
(long 배열로 관리) 반환
- 64개 이하면
EnumSet
하위 타입이기만 하면된다.
- 아래 코드는 원소가
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);
}
- 5. 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
- 이 점을 활용해 만든 것이 서비스 제공자 프레임워크에서의 서비스 접근 API
👉🏻 서비스 제공자 프레임워크(Service provider framework)
프레임워크가 클라이언트를 서비스의 구현체(제공자(provider))로 부터 분리해준다.
서비스 제공자 프레임워크의 핵심 컴포넌트
- 서비스 인터페이스(service interface)
: 구현체의 동작을 정의 - 제공자 등록 API(provice registration API)
: 제공자가 구현체를 등록할 때 사용 - 서비스 접근 API(service access API)
: 클라이언트가 서비스의 인스턴스를 얻을 때 사용
- 서비스 제공자 프레임워크의 근간인 유연한 정적 팩터리의 실체
조건을 명시하지 않으면 기본 구현체를 반환하거나 지원하는 구현체들을 돌아가면서 반환한다.
- 서비스 제공자 프레임워크의 근간인 유연한 정적 팩터리의 실체
- 서비스 제공자 인터페이스(service pro-vider interface)
: 서비스 인터페이스의 인스턴스를 생성하는 팩터리 객체를 설명
- 없으면 구현체를 인스턴스로 만들 때 리플렉션을 사용해야한다.
JDBC(JavaDatabase Connectivity) (java 5 이전)
대표적인 서비스 제공자 프레임워크
- Connection: 서비스 인터페이스
- DriverManager.registerDriver: 제공자 등록 API
- DriverManager.getConnection: 서비스 접근 API
- Driver: 서비스 제공자 인터페이스
DI(dependency injection) 프레임워크도 서비스 제공자 프레임워크
java.util.ServiceLoader: 범용 서비스 제공자 프레임 워크 (java 5부터)
단점
- 정적 팩터리 메서드만 제공하면 하위 클래스를 만들 수 없다. (제약)
상속을 하려면 public이나 protected 생성자가 필요하기 때문이다. - 정적 팩터리 메서드는 찾기 힘들다.
- API설명에 명확히 드러나지 않아 정적 팩터리 메서드 방식 클래스를 인스턴스화할 방법을 알아내야 한다.
728x90
LIST
'Language > JAVA' 카테고리의 다른 글
[Effective Java] private 생성자와 열거 타입으로 싱글턴 보증하기 (0) | 2023.08.10 |
---|---|
[JAVA][자료구조] Stack (0) | 2023.08.09 |
[JAVA][자료구조] Queue (0) | 2023.08.09 |
[Effective java] private 생성자 - 인스턴스화 막기 (0) | 2023.07.28 |
[JAVA] Comparator, Comparable을 이용해서 배열과 List를 정렬하자. (0) | 2023.07.28 |