Item 1. 정적 팩터리 메소드

심규환·2022년 1월 6일
0

Effective Java

목록 보기
1/29
post-thumbnail

클라이언트가 클래스의 인스턴스를 얻기 위해서 많이 사용하는 방법은 public 생성자이다. 하지만 클래스는 생성자와 별도로 정적 팩터리 메소드(static factory method)를 제공할 수 있다.
정적 팩터리 메소드란 그 클래스의 인스턴스를 반환해주는 메서드이다.
그러면 이 정적 팩터리 메소드의 장단점을 알아보자.

<장점>

첫 번째, 이름을 가질 수 있다.
생성자를 통해서 반환된 인스턴스는 반환될 객체의 특성을 예측할 수 없다. 매개변수의 갯 수의 차이로 어떤게 나올까 대충 유추할 수 있을지 모르겠지만 일반적으로 구현체를 읽어보지 않으면 정확하게 알 수가 없다.
하지만 정적 팩터리 메소드를 사용하여 이름을 지으면 반환될 객체의 특성을 묘사할 수 있다. 정적 팩터리 메소드의 이름을 반환할 인스턴스의 특징을 적어 놓으면 개발자도 쉽게 인스턴스의 특징을 유추할 수 있다. 여기서 중요한 것은 이름을 잘 지어야 한다는 것이다.

두 번째, 인스턴스를 새로 생성하지 않아도 된다.
이 덕분에 불변 클래스는 인스턴스를 미리 만들어 놓거나 새로 생성한 인스턴스를 캐싱하여 재활용하는 방식으로 불필요한 객체 생성을 피할 수 있다. 이는 이 객체를 통제할 수 있음을 의미한다. 반복적인 호출에도 항상 같은 인스턴스를 반환하게 하여 유지하게할 인스턴스를 철저하게 통제가 가능하다.

세 번째, 반환할 인스턴스 타입의 하위 타입 객체를 반환할 수 있다.
반환할 객체의 클래스를 자유롭게 선택할 수 있다는 것은 '엄청난 유연성'을 의미한다. 이는 API를 작게 유지할 수 있다는 말이 된다. 그럼 API를 작게 유지한다는 말은 무엇일까?
클라이언트는 객체의 인터페이스만 알고 있고, 인터페이스에는 기본적인 메서드들이 선언되어 있다. 클라이언트가 이 인터페이스의 기능들을 사용할 때, 내부적으로 생성된 구현체들을 굳이 알 필요가 없다. 즉, 인터페이스가 따로 추가적인 성능 튜닝을 한 클래스나 새로운 기능을 가진 클래스를 구현체로 만들어도 인터페이스는 그대로 두고 해당 클래스만 반환하면 되기 때문이다.

네 번째, 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
반환 타입의 하위 타입이기만 하면 어떤 클래스를 반환해도 상관없기 때문에 입력 매개변수에 따라 알맞은 클래스를 반환해 줄 수 있다.
예를 들어, EnumSet 클래스는 원소의 수에 따라 두 가지 하위 클래스 중 하나를 반환한다. 원소가 64개 이하면 원소 RegularEnumSet의 인스턴스를, 65개 이상이면 JumboEnumSet의 인스턴스를 반환한다.
클라이언트는 이 클래스들을 몰라도 된다. 보다 나은 클래스가 만들어지면 RegularEnumSet을 다음 릴리즈 때, 삭제해도 무관하다.

다섯 번째, 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
반환할 객체의 클래스가 존재하지 않아도 된다는 말이 무슨 말일까?
이는 정적 팩터리 메서드를 작성하는 시점, 즉, XXX.getInstance(temporary) 를 할 때, 반환할 클래스가 존재하지 않아도 된다는 것이다.
이런 유연함은 서비스 제공자 프레임워크(service provider framework)를 만드는 근간이 된다.
서비스 제공자 프레임워크는 3개의 핵심 컴포넌트로 이루어 진다. 서비스 인터페이스, 서비스 접근 API, 제공자 등록 API 가 이 세가지 이다.

• 서비스 인터페이스(service interface) : 구현체의 동작을 정의하는 서비스 인터페이스
• 서비스 접근 API(service access API) : 클라이언트가 서비스의 인스턴스를 얻을 때 사용
• 제공자 등록 API(provider registration API) : 제공자가 구현체를 등록할 때 사용한다. 

클라이언트가 서비스 접근 API를 사용할 때, 원하는 구현체 조건을 명시할 수 있다. 이때 조건을 명시하지 않으면 기본 구현체를 반환하거나 지원하는 구현체들을 하나씩 돌아가면서 반환한다. 이는 '유연한 정적 팩터리'를 나타낸다.

<단점>

첫 번째, 정적 팩터리만 제공한다면 상속이 불가능하다.
상속을 위해 public or protected 생성자가 필요한데. 정적 팩터리만 제공한다면 하위 클래스를 만들 수 없게 된다.

두 번째, 프로그래머가 찾기 어렵다.
생성자의 경우, 그 이름으로 유추하거나 찾아보면 되는데. 정적 팩터리 메서드의 경우, 설명이 명확하게 드러나지 않으니 사용자가 인스턴스화 할 방법을 알아내야 한다. 그렇기 때문에 메서드 이름 짓는게 정말 중요하다 !

profile
장생농씬가?

0개의 댓글