[Effective Java] 규칙1: 생성자 대신 정적 팩터리 메서드 고려해보기
클래스를 통해 객체를 만드는 방법은 세 가지가 있다.
- public으로 선언된 생성자
- 정적 팩터리 메서드
- 빌더 패턴
위의 세 가지 방법 중 가장 일반적인 것은 첫 번째 방법인데, 이 대신에 정적 팩터리 메서드를 사용할 수는 없는지 고려해보자.
정적 팩터리 메서드를 이용해 객체를 만드는 하나의 예시는 아래와 같다.
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
1. 생성자 대신 정적 팩터리 메서드를 사용할 때의 장점
첫 번째, 생성자와는 달리 정적 팩터리 메서드에는 이름이 있다.
예를 들어, 소수일 가능성이 높은 BigInteger 객체를 생성하는 생성자 BigInteger(int, int, Random)
대신 BigInteger.probablePrime
처럼 표현하면 반환받을 객체에 대한 정보를 이름으로부터 대략 파악할 수 있게 된다.
두 번째, 생성자와는 달리 호출할 때마다 새로운 객체를 생성할지 또는 같은 객체를 반환할지(싱글톤) 선택할 수 있다.
위에서 예를 든 valueOf
메서드처럼 객체가 매번 생성되는 일을 피할 수 있다. 같은 객체를 반복해서 반환하게 되면 어떤 시점에 어떤 객체가 얼마나 존재할지를 정밀하게 제어할 수 있게 된다.
세 번째, 생성자와는 달리 반환 타입을 가지므로 상속 또는 구현체를 반환하도록 하는 전략을 구성할 수 있다.
정말 강력한 장점이라고 생각하는데 예를 들어, 특정 인터페이스를 반환 타입으로 가진다면 그 어떤 구현체를 반환할지를 내부 로직에서 선택할 수 있다. 여기서 주의할 점은, 인터페이스 자체는 정적 메서드를 가질 수 없기 때문에 관습상 반환 타입이 Type
이라는 이름의 인터페이스인 정적 팩터리 메서드는 Types
라는 이름의 객체 생성 불가능 클래스 안에 둔다.
예를 들어, Java의 컬렉션 프레임워크에는 32개의 컬렉션 인터페이스 구현체가 들어 있는데, 이 구현체들 거의 전부는 java.util.Collections라는 객체 생성 불가능 클래스의 정적 팩터리 메서드를 통해 이용한다.
2. 정적 팩터리 메서드명으로 사용되는 것들
일반적으로 다음과 같은 이름을 정적 팩터리 메서드명으로 사용한다.
valueOf
: 인자로 주어진 값과 같은 값을 갖는 객체를 반환한다는 뜻으로 이런 정적 팩터리 메서드를 형변환 메서드라 한다.of
: valueOf를 더 간단하게 쓴 것.getInstance
: 인자에 기술된 객체를 반환하지만, 인자와 같은 값을 갖지 않을 수도 있다. 싱글턴 패턴을 따를 경우 이 메서드는 인자 없이 항상 같은 객체를 반환한다.newInstance
:getInstance
와 같지만 호출할 때마다 다른 객체를 반환한다.getType
:getInstance
와 같지만, 반환될 객체의 클래스와 다른 클래스에 팩터리 메서드가 있을 경우에 사용한다. 예를 들어, Type은 팩터리 메서드가 반환할 객체의 타입이다.newType
:newInstance
와 같지만, 반환될 객체의 클래스와 다른 클래스에 팩터리 메서드가 있을 경우에 사용한다. 예를 들어, Type은 팩터리 메서드가 반환할 객체의 타입이다.
'Programming > Effective Java' 카테고리의 다른 글
[Effective Java] 규칙2: 생성자 인자가 많다면 Builder 패턴 고려해보기 (0) | 2020.07.29 |
---|