본문 바로가기
Language/Java

이펙티브 자바 - 정적 팩토리 메소드

by ocwokocw 2021. 9. 5.

- 이 글은 Effective Java 를 기반으로 작성되었습니다.

- 정적 팩토리 메소드

객체를 생성하는 일반적인 방법은 public 생성자를 이용하는것이다. 하지만 정적 팩토리 메소드를 이용할 수도 있다. Boolean 의 valueOf 메소드는 기본 타입의 boolean 을 Boolean 객체 참조로 변환한다.

 

public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; }

 

흔히 정적 팩토리 메소드를 디자인 패턴의 팩토리 메소드와 혼동한다. 

 

디자인 패턴의 팩토리 메소드는 하나의 환경변수나 다른 변수를 (팩토리)만 변경하면 제품군들도 일괄적으로 변경되어 생성되도록 하는 패턴이다. 예를 들어 객체 RadioA1과 TVA1 이 있고 RadioB1과 TVB1 이 있고 Radio 객체를 생성하는 메소드를 createRadio(), TV 를 생성하는 메소드를 createTV() 라고 가정해보자. 이때 RadioA1과 TVA1 이 생성되는 상태에서 환경 변수(팩토리) 변경에 따라 생성 메소드를 호출했을 때 일괄적으로 RadioB1과 TVB1 이 생성해주도록 하는 패턴이다.

 

정적 팩토리 메소드는 이런 디자인 패턴과는 개념이 약간 다르다. 정적 패토리 메소드의 장단점을 알아보자.


- 장점

1. 생성자는 클래스명을 통해 생성해야 하지만 정적 팩토리 메소드에는 이름이 있다. 정적 팩토리 메소드는 이름을 잘 짓기만 하면 전달되는 인자에 따라 어떤 생성자가 생성될지 알 수 있어서 가독성이 높아진다.

 

2. 생성자와 달리 호출시마다 새로운 객체를 생성할 필요가 없어진다. 변경 불가능 클래스라면 매번 생성할 필요없이 미리 생성해준 객체를 재활용할 수 있다. 또한 캐싱도 가능하다. 위에서 예제로 보았던 Boolean.valueOf 도 이와 마찬가지다. 객체의 생성을 제어할 수 있게 되면 어떤 시점에 어떤 객체가 얼마나 존재할지를 더 정밀하게 제어할 수 있다. 이를 개체 통제 클래스라고 한다.

 

3. 정적 팩토리 메소드는 반환값 자료형의 하위 자료형 객체를 반환할 수 있다. 반환되는 객체의 클래스를 훨씬 유연하게 결정할 수 있어서 다형성 개념의 적용도 가능해진다. 

 

4. 형인자 자료형(Template) 객체를 만들때 편리하다. 자바 1.7 의 다이아몬드 연산자 이전에는 Map 제네릭에 자료형을 명시하더라도 그의 구현체인 HashMap 에 아래처럼 동일한 자료형을 중복으로 명시했었다.

 

Map<String, List<String>> m = new HashMap<String, List<String>>();

 

정적 팩토리 메소드를 이용하면 이를 좀 더 깔끔하게 감출 수 있다.

 

public static <K, V> HashMap<K, V> newInstance(){
    return new HashMap<K, V>();
}

 

지금은 자바 1.7 에서 다이아몬드 연산자를 지원하면서 형유추가 가능해졌다.

 

Map<String, List<String>> m = new HashMap<>();

- 단점

1. public 이나 protected 생성자 없이 정적 팩토리 메소드에서만 생성을 지원하는 클래스를 만들면 하위 클래스를 만들 수 없다. Collection 프레임워크에 포함된 기본 구현 클래스들의 하위 클래스는 만들 수 없다. 그래서 더 좋다는 사람도 있는데 상속대신 구성(Composition)을 쓰도록 장려한다.

 

2. 다른 정적 메소드와 확연하게 구분되지 않는다. 생성자는 다른 메소드와 확연하게 구분되지만 정적 팩토리 메소드는 다른 정적 메소드와 확연하게 구분되지 않는다. 그래서 이름을 잘 지을 수 밖에는 없다. 보통은 아래와 같은 이름을 많이 사용한다.

  • valueOf(of): 인자로 주어진 값과 같은 값을 갖는 객체 반환
  • getInstance: 인자에 기술된 객체를 반환하지만 같은 값을 갖지 않을 수도 있다.
  • newInstance: getInstance 와 같지만 호출마다 다른 객체 반환

- 마치면서

정적 팩토리 메소드의 장단점을 분명히 말하고 있음에도 불구하고 책대로 해야 한다고 생각하는 사람들은 '생성자 대신 무조건 정적 팩토리 메소드를 이용해야겠따' 라고 생각할 수 있는데 말 그대로 장단점이 있다.

 

책내용 대로 무작정 팩토리 메소드 형식으로 하거나 관습적으로 무조건 public 생성자를 쓰지 말고 각각 장단점을 잘 파악하여 상황에 맞게 써야할 것이다. 

'Language > Java' 카테고리의 다른 글

이펙티브 자바 - 싱글턴 패턴  (0) 2021.09.18
이펙티브 자바 - Builder 패턴  (0) 2021.09.16
[Java 8] 날짜 API - 2  (0) 2021.02.11
[Java 8] 날짜 API - 1  (0) 2021.02.11
[Java 8] CompletableFuture - 4 (종료조건)  (0) 2021.02.11

댓글