[01] 생성자 대신 정적 팩터리 메서드를 고려하라
핵심 내용
클래스를 생성할 때, 클래스의 생성자를 이용하는 방법 외에 정적 메소드를 사용해서 클래스를 얻는 방법도 고려하라는 것이다.
클래스는 생성자와 별도로 정적 팩터리 메서드(static factory method)를 제공 할 수 있다. 그 클래스의 인스턴스를 반환하는 단순한 정적 메서드 말이다.
'정적 팩터리 메서드' 라는 표현이 그리 보편화 되어있는 것 같진 않은데 마치 원래 규정된 의미처럼 저자가 사용하고 있다.
아무튼 생성자로 만드는 방법 외에 '경우에 따라' 정적 팩터리 메서드로 객체를 얻는 것을 고려하라는 의미이다.
어떤 상황일 때 정적 팩터리 메서드를 고려하는 것이 좋을까(= 정적 팩터리 메서드를 이용해서 객체를 얻을 때의 장점)
이름을 가질 수 있다
객체 생성시 명확한 의도를 담을 수 있다
객체를 얻을 때(생성한다는 표현을 쓰지 않은 것은 기존에 이미 생성된 것을 가져올 수도 있기 때문이다) 이름을 가지고 객체를 얻어 오면 코드 상에서 더 명시적으로 의도를 드러낼 수 있다. dart 의 named constructor 가 정확한 예시이다.
위 코드는 프로젝트 내에 사용한 LoadingSpinnerState 객체를 가져오는 코드인데 LoadingSpinnerState() 생성자에 인자를 넣어주지 않고 processing, finished 와 같이 해당 객체의 상태에 대한 의도를 정확하게 드러내면서 객체를 가져오고 있다.
파라미터가 같아서 시그니처가 같아버리는 문제를 회피할 수 있다
위와 같이 논리적 의미로 파라미터는 구분 되지만 결론적으로 시그니처는 같기 때문에 컴파일 에러가 발생한다. 파라미터의 순서를 바꾸는 꼼수를 통해서 극복할 수는 있지만 좋은 해결 방법은 아니다.
호출 될 때마다 인스턴스를 새로 생성 하지는 않아도 된다
생성자를 쓴다는 것은 무조건 새로운 객체가 생성이 된다는 이야기이다. 반면 정적 팩토리 메서드를 통해서 객체를 얻는 것은 말 그대로 메서드를 통해서 얻는 것이기에 클라이언트 입장에서는 이 메서드가 내부적으로 새로 객체를 생성해서 주는 것인지, 이미 만들어진 객체를 반환하는 것인지 알 수 없다.
이러한 의미에서 싱글톤 패턴에서 .newInstance() 를 통해서 이미 만들어진 객체를 할당 받는 것처럼 정적 팩터리 메서드를 통해서 생성 비용을 치르지 않고 이미 만들어진 객체를 받을 수 있다는 것이다.
책에서 이 부분에서 플라이웨이트 패턴에 대해서 언급하고 있는데, 공유 할 수 있는 객체를 서로 공유하는 패턴이라서 맥락이 통한다.
반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다 + 입력 매개 변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
책에서 언급하고 있는 장점 세번째와 네번째를 묶었다. 왜냐면 내용이 맞닿아 있기 때문이다. 리턴 타입을 추상화된 상위 객체로 받되, 실제 구현체는 파라미터를 통해서 제어할 수 있다는 내용이다. 루즈 커플링을 실현하는 형태가 된다. 유연한 설계인 것이다.
정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다
책에서는 '서비스 제공자 프레임워크' 라는 것을 언급하고 있는데 서비스 로더를 이용해서 추상화된 인터페이스로 구현체를 로드해서 사용하는 것을 말하고 있다.
핵심은 클라이언트 객체가 전혀 서비스에 '의존'하지 않고 오로지 추상화된 인터페이스에만 의존하고 서비스를 로드해서 사용한다는 것이다. 그러면 클라이언트는 사실 무엇이 로드 될지 '모르는' 상태에서 인터페이스에 의존해서 이를 사용하는 것이다.
예를 들면 JDBC 가 있는데, DB 벤더가 무엇이 올지 몰라도 구현이 가능한 것과 일맥상통한다. 서비스 제공자 프레임워크를 자세히 다루는 것은 좀 학습 가성비가 떨어지는 것 같아서 여기서는 생략한다.
정적 팩터리 메서드를 사용했을 때의 단점
이건 책에서 두 가지를 말하고 있긴 한데, 개인적으로 막 동의가 가진 않아서(억지로 저자가 끼워 넣은 느낌) 간략하게 만 정리하겠다.
상속을 하려면 public 이나 protected 생성자가 필요하니 정적 팩터리 메서드만 제공하면 하위 클래스를 만들 수 없다
당연한 이야기인데 이게 단점이라 언급되는게 약간 이상하다. 왜냐면 단점이란건 '불가피'한 성격이 있어야 하는데 이 경우는 그냥 public 생성자를 만들어주면 그만이다. 싱글톤 패턴처럼 생성을 막아야 하는 것이 아니라면 public 생성자를 제공해줌으로써 정적 팩토리 메서드와 병행에서 사용하면 될 것이다.
정적 팩터리 메서드는 프로그래머가 찾기 어렵다
저자는 자바독을 열심히 활용한다는 기준으로 이 부분을 언급하고 있다. generated 된 자바독에는 정적 팩터리 메서드가 객체의 생성을 역할을 하는지는 안나오니까 그런 것 같다.(정적 팩터리 메서드가 자바독 내에서 생성자로 분류가 안되나보다)
Last updated