아이템1. 생성자 대신 정적 팩토리 메서드를 고려하라
정적 팩토리 메서드(Static Factory Method)란?
직접적으로 생성자를 통해 객체를 생성하는 것이 아닌 메서드를 통해서 객체를 생성하는 것을 정적 팩토리 메서드라고 한다.
객체 생성의 역할을 하는 클래스 메서드 라는 의미이다.
- 클래스는 클라이언트에게 public 생성자 대신 static 팩토리 메서드를 제공할 수 있다.
- 여기서 말하는 팩토리 메서드는 디자인 패턴에서 나오는 팩토리 메서드 패턴과 다른 의미이다.
생성자와의 차이는?!
실제로 정적 팩토리 메서드가 어떤 방면에서 생성자보다 좋은지 하나씩 알아보자.
1. 이름을 가질 수 있다.
public class Board {
pricate String title;
//일반적인 생성자를 만들어서 사용하는 경우
private Board(String title) {
this.title = title;
}
//정적 팩토리 메서드 사용
//createdBoard라는 이름을 가지게 되어 명시적인 선언 가능
public static Board createdBoard(String title) {
return new Board(title);
}
- 단순히 생성자를 만들어 사용하는 경우는 단번에 보았을 때 의미를 알 수 없을 수 있다.
- 하지만 정적 팩토리 메서드를 사용해서 만든 createdBoard 메서드는 어떤 역할을 하는지 단번에 이해할 수 있다.
- 이처럼 정적 팩토리 메서드를 사용하면 해당 생성의 목적을 이름에 표현할 수 있어 가독성이 좋아지는 효과가 있다.
2. 호출할 때 마다 새로운 인스턴스(객체)를 생성할 필요가 없다.
- 이에 대한 예시는 enum이 대표적이다.
- 인스턴스를 미리 만들어 놓거나 새로 생성한 인스턴스를 캐싱하여 재활용하는 식으로 불필요한 객체 생성을 피할 수 있다.
- 따라서 같은 객체가 자주 요청되는 상황이라면 성능을 상당히 끌어올려 준다.
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
// private 생성자
}
public static Singleton getInstance() {
return INSTANCE;
}
}
3. 반환 타입의 하위 타입 객체를 반환할 수 있다.
하위 자료형 객체를 반환하는 정적 팩토리 메서드의 특징은 상속을 사용할 때 확일 할 수 있다.
이는 생성자의 역할을 하는 정적 팩토리 메서드가 반환값을 가지고 있이 때문에 가능한 특징이다.
Basic, Intermediate, Advanced 클래스가 Level이라는 상위 타입을 상속받고 있는 구조를 생각해보자.
시험 점수에 따라 결정되는하위 등급 타입을 반환하는 정적 팩토리 메서드를 만들면, 다음과 같이 분기처리를 통해 하위 타입의 객체를 반환할 수 있다.
public class Level {
...
public static Level of(int score) {
if (score < 50) {
return new Basic();
} else if (score < 80) {
return new Intermediate();
} else {
return new Advanced();
}
}
...
}
4. 객체 생성을 캡슐화 할 수 있다.
대표적인 예시로는 계층 간에 데이터를 전송하기 위한 객체로 DTO를 정의해서 사용한다.
DTO와 Entity간에는 자유롭게 형 변환이 가능해야 하는데, 정적 팩토리 메서드를 사용하면 내부 구현을 모르더라도 쉽게 변환할 수 있다.
public class CarDto {
private String name;
private int position;
pulbic static CarDto from(Car car) {
return new CarDto(car.getName(), car.getPosition());
}
}
// Car -> CatDto 로 변환
CarDto carDto = CarDto.from(car);
만약 정적 팩토리 메서드를 쓰지 않고 DTO로 변환한다면 외부에서 생성자의 내부 구현을 모두 드러낸 채 해야할 것이다.
Car carDto = CarDto.from(car); // 정적 팩토리 메서드를 쓴 경우
CarDto carDto = new CarDto(car.getName(), car.getPosition); // 생성자를 쓴 경우
이처럼 정적 팩토리 메서드는 단순히 생성자의 역할을 대신하는 것 뿐만 아니라, 우리가 좀 더 가독성 좋은 코드를 작성하고 객체지향적으로 프로그래밍할 수 있도록 도와 준다.
5. 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
매개변수에 따라 원하는 클래스 객체를 반환할 수 있으므로 상황에 따라 효율적인 객체를 만들 수 있다.
public interface Number {
static Number createNumber(int num){
if (num > -1000 && num < 1000){
return new SmallNum();
}
return new BigNum();
}
}
class SmallNum implements Number{
}
class BigNum implements Number{
}
- Number란 인터페이스가 있을 때 매개변수의 값이 작으면 SmallNum을 반환해주고 크면 BigNum을 반환해주어 효율적으로 메모리를 사용하게 할 수도 있습니다.
정적 팩토리 메서드 네이밍 컨벤션
- from : 하나의 매개 변수를 받아서 객체를 생성
- of : 여러개의 매개 변수를 받아서 객체를 생성
- getInstance / instance : 인스턴스를 생성, 이전에 반환했던 것과 같을 수 있음
- newInstance / create : 새로운 인스턴스를 생성
- get[OtherType] / create : 새로운 인스턴스를 생성
- new[OtherType] : 다른 타입의 새로운 인스턴스를 생성
참고 블로그 문서
https://devnoong.tistory.com/70
https://tecoble.techcourse.co.kr/post/2020-05-26-static-factory-method/
'도서 > 정리' 카테고리의 다른 글
[이펙티브 자바] 아이템6. 불필요한 객체 생성을 피하라 (0) | 2023.05.15 |
---|---|
[이펙티브 자바] 아이템5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) | 2023.05.09 |
[이펙티브 자바] 아이템4. 인스턴스화를 막으려거든 private 생성자를 사용하라 (1) | 2023.05.07 |
[이펙티브 자바] 아이템3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 (0) | 2023.05.05 |
[이펙티브 자바] 아이템2. 생성자에 매개변수가 많다면 빌더를 고려하라 (0) | 2023.05.04 |