티스토리 뷰
생성자 대신 정적 팩터리 메서드를 고려하라
정적 팩터리 메서드가 가지는 장점
이름을 가질 수 있다.
생성자를 통해서 객체를 생성하다보면 그 객체가 어떤 정보를 포함하여 생성하는지 정확히 모를 때가 많다.
또한, 생성자를 볼때 주석이나 설명 문서를 읽어야하는 수고로움을 덜어줄 수 있다.
public class Student{
private String name;
public Student(){}
public Student(String name){
this.name = name;
}
public static Student nameOf(String name){
return new Student(name);
}
}
다음과 같은 소스 코드에서 그냥 생성자를 통해서와 nameOf라는 정적 팩터리 메서드를 통해서 생성한 것의 차이를 볼 수 있다.
Student s1 = new Student("kim");
Student s2 = Student.nameOf("park");
이 것은 간단한 예시라서 이점이 잘 와닿지 않을 수 있지만 복잡하게 인자가 들어간다면 확실한 이득을 볼수 있을 것이다.
호출될 때마다 인스턴스를 새로 생성하지는 않아도 된다.
반복되는 요청에 같은 객체를 반환하는 식으로 정적 팩터리 방식의 클래스는 언제 어느 인스턴스를 살아있게 할지를 철저히 통제가 가능하다.
예시) 싱글턴 패턴
public class Student{
private static Student student = null;
private Student(){}
static Student getInstance(){
if(student ==null){
student = new Studnet();
}
return student;
}
}
또한 불필요한 객체 생성도 피할 수 있다는 점도 있다.
Boolean의 valueOf를 보면 객체를 생성하지 않아 불필요한 메모리의 소진을 하지 않았다.
public static Boolean valueOf(boolean b){
return b ? Boolean.TRUE : Boolean.FALSE;
}
반환 타입의 하위 객체를 반환할 수 있는 능력이 있다.
이렇게 하면 구현 클래스를 공개하지 않고 객체를 반환할 수 있어 API를 작게 유지 가능하다.
이는 인터페이스 기반 프레임워크를 만드는 핵심 기술이다.
public interface Food{}
public class Chicken extends Food{}
public class Pizza extends Food{}
public class Order{
public static Food findFood(String code){
if(isInvalidCode(code)){
throw new Exception("잘못된 음식 코드");
}
if(isChicken(code)){
return new Chicken();
} else if(isPizza(code)){
return new Pizza();
}
}
}
(적힌 예시가 상황에 부합하지는 않은것 같지만...)
간단하게 살펴보면 Order과 같은 클래스에서는 Food라는 인터페이스의 구현을 모른채로 반환 할 수 있게 된다.
이렇게 하면 굳이 Order을 만들지 않고도 Food를 찾을 수 있게 된다.
입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
간단하게 말하면 사용자가 정적 팩터리를 사용할때 생성되는 객체가 어느 객체인지 정확히 구분해서 사용할 필요 없이 생성 조건을 통제하여 생성되게 할 수 있다는 점이다.
EnumSet에서 해당 내용을 사용하고 있다.
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
Enum<?>[] universe = getUniverse(elementType);
if (universe == null)
throw new ClassCastException(elementType + " not an enum");
if (universe.length <= 64)
return new RegularEnumSet<>(elementType, universe);
else
return new JumboEnumSet<>(elementType, universe);
}
다음처럼 분기문을 통해서 길이가 64이하면 RegularEnumSet을 반환하고 이상이면 JumboEnumSet를 반환하는 것을 확인 할 수 있다.
단점
- 정적 팩터리 메서드만 있는 클래스는 하위 클래스를 만들 수 없다.(생성자가 public이나 protected 필요). => 컴포지션을 통해서 해결 가능
- 정적 팩터리 메서드는 프로그래머가 찾기 어렵다. => 규약에 따라서 명명해주는 것이 좋다.
'Programming_language > Java' 카테고리의 다른 글
Class 내 Method 추상화(Feat. Consumer, BiConsumer, Function) (1) | 2024.10.09 |
---|---|
[Effective Java] 4. 참조 해제 (0) | 2022.11.09 |
[Effective Java] 3. 의존 객체 주입 (0) | 2022.11.09 |
[Effective Java] 2. 빌더 패턴 (0) | 2022.11.09 |
- Total
- Today
- Yesterday
- centos
- feign client
- React
- consumer
- Linux
- apache
- apache kafka
- NextJS
- broker
- Java
- spring boot
- docker
- Data Engineering
- API
- cs
- Front
- rhel
- Firebase
- 리액트
- Container
- OS
- frontend
- 프론트엔드
- zookeeper
- KAFKA
- JPA
- spring
- K8S
- Producer
- logback
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |