정적 팩터리 메서드 고려하기
•
생성자를 호출하여 클래스를 만드는 대신 of나 valueOf와 같은 클래스의 팩터리 메서드를 두고 그를 통해 생성하자
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
Java
복사
•
생성자를 private로 숨기고 위와 같이 정적 팩터리 메서드를 제공하는 것을 고려하자.
정적 팩터리 메서드의 장점
•
이름을 가질 수 있다.
◦
아래 예시에 정적 팩터리 메서드가 소수인 BigInteger를 반환한다는 의미를 잘 전달하는 것 처럼, 팩터리 메서드를 사용하면 하나의 클래스에 시그니처가 같은 여러 개의 생성자를 호출할 수 있고 각각 차이를 드러내는 이름을 지어줄 수 있다.
// 생성자 호출
new BigInteger(...);
// 정적 팩터리 메서드 호출
BigInteger.probablePrime(...);
Java
복사
•
호출될 때마다 인스턴스를 새로 생성하지 않아도 된다.
◦
불변 클래스로 팩터리 메서드를 미리 만들어놓거나 인스턴스를 캐싱하여 재활용하여 불필요한 객체 재생성을 피할 수 있다.
◦
인스턴스의 생명주기를 관리하는 인스턴스 통제 클래스를 통해, 싱글턴이나 인스턴스화 불가로 만들 수도 있다.
•
반환 타입의 하위 타입 객체를 반환할 수 있다.
◦
정적 팩터리 메서드로 반환할 객체의 클래스를 자유롭게 선택할 수 있는 유연성을 가질 수 있다.
◦
이 유연성을 활용하면 구현 클래스를 공개하지 않고 해당 객체를 반환하는게 가능해진다. 이를 통해 API를 작게 유지하여 유지보수성을 높일 수 있다.
•
입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
◦
위의 반환 타입의 하위 타입 객체를 반환할 수 있다는 장점의 연장선으로, 반환 타입의 하위 타입이기만 하면 어떤 클래스의 객체를 반환하든 상관이 없다.
◦
EnumSet의 경우 public 생성자를 제공하지 않고 정적 팩터리 메서드만 제공하는데, 원소가 64개 이하면 RegularEnumSet을 반환하고 65개 이상이면 JumboEnumSet을 반환한다.
•
정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
◦
JDBC(Java Data Connectivity)와 같은 서비스 제공자 프레임워크들의 근간이 되는 기능으로, 클라이언트를 구현체와 분리해준다.
◦
서비스 제공자 프레임워크는 3개의 핵심 컴포넌트로 이루어진다.
▪
구현체의 동작을 정의하는 서비스 인터페이스
▪
제공자가 구현체를 등록할 때 사용하는 제공자 등록 API
▪
클라이언트가 서비스의 인스턴스를 얻을 때 사용하는 서비스 접근 API
정적 팩터리 메서드의 단점
•
상속 하려면 public이나 protected 생성자가 필요하기 때문에, 정적 팩터리 메서드만 제공하면 하위 클래스를 만들 수 없다.
◦
이 제약은 사실 컴포지션을 사용하고 불변 타입으로 만들 때 오히려 장점이 될 수 있다.
•
정적 팩터리 메서드는 프로그래머가 찾기 어렵다.
◦
정적 팩터리 메서드는 생성자처럼 API에 드러나지 않으니, 사용자가 정적 팩터리 메서드 방식을 사용하는 방법을 알아야 한다.
정적 팩터리 메서드 명
•
from
◦
매개변수를 하나 받아서 해당 타입의 인스턴스를 반환하는 정적 팩터리 메서드
Date d = Date.from(instant);
Java
복사
•
of
◦
여러 매개변수를 받아 적합한 타입의 인스턴스를 반환하는 정적 팩터리 메서드
Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);
Java
복사
•
valueOf
◦
from과 of의 더 자세한 버전
BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
Java
복사
•
instance / getInstance
◦
매개변수로 명시한 인스턴스를 반환하지만, 같은 인스턴스임을 보장하지는 않는 정적 팩터리 메서드
StackWalker luke = StackWalker.getInstance(options);
Java
복사
•
create / newInstance
◦
instance나 getInstance와 같지만, 매번 새로운 인스턴스를 생성하여 반환하는 것을 보장하는 정적 팩터리 메서드
Object newArray = Array.newInstance(classObject, arrayLen);
Java
복사
•
getType
◦
getInstance와 같지만, 생성할 클래스가 아니라 다른 클래스에 팩터리 메서드를 정의할 때 사용되는 정적 팩터리 메서드
FileStore fs = Files.getFileStore(path);
Java
복사
•
newType
◦
newInstance와 같지만, 생성할 클래스가 아니라 다른 클래스에 팩터리 메서드를 정의할 때 사용되는 정적 팩터리 메서드
BufferedReader br = Files.newBufferedReader(path);
Java
복사
•
type
◦
getType과 newType의 간결한 버전
List<Complaint> litany = Collections.list(legacyLitany);
Java
복사