일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 코드트리
- 부꾸
- 후기
- 보따리
- 사이드 프로젝트
- 프로그래머스
- redis
- 동적 SQL
- 체험
- 모의면접
- 트러블슈팅
- 북극곰
- 글또 #다짐
- open contribution jam
- 글또
- dto projection
- 오블완
- jscode
- jooq
- SQL
- spring context
- 눈송이
- DI
- Spring
- 부꾸러미
- Database
- 구슬
- bean
- 테오의 스프린트
- 티스토리챌린지
- Today
- Total
벤티의 개발 로그
[Java] 정적 팩토리 메서드 뜯어보기 본문
from? of?
예전에 다른 백엔드 팀원과 코드를 합칠 때, 매우 난해했던 것이 있었다. 바로 DTO 클래스에 from
, of
이라는 이름을 가진 메서드들이 있는 것이었다. 개인적으로 메서드나 변수 이름을 지을 때, '누가, 언제, 어디서' 확인해도 어떤 역할을 하는지 파악할 수 있도록 하는 것이 중요하다고 생각하여 길게 짓는 편이었기 때문에 당황스러웠다. 당시 시간이 없었기 때문에 그냥 넘어갔으나, 얼마 전 다른 분의 코드에서도 비슷한 메서드들을 발견해서 '얘네는 뭘까?'라는 의문점이 생겼다.
정적 팩토리 메서드
구글링을 해보니, 그런 메서드들은 정적 팩토리 메서드(Static Factory Method) 라고 한다. 예전에 디자인 패턴에 관해서 공부한 적이 있는데, 그중 하나인 '정적 팩토리 패턴'과 비슷한 건가 싶었지만, 이 기회에 확실하게 짚고 넘어가자는 생각에 정리하기로 했다.
장점
주로 DTO 클래스에서 @Builder
나 생성자를 사용했기 때문에 일단 왜 쓰는 지 부터 알아봤다. 크게 장점은 아래와 같았다.
- 생성자는 특별한 의미를 갖지 않는다.
'응? 무슨 의미지?' 싶었지만 생성자나 소멸자는 클래스의 이름과 같은 이름만을 가질 수 있기 때문에 그렇다고 한다. 맞는 말이다. - 정적 팩토리 메서드는 반환 자료형의 하위 타입, 반환 자료형의 원시 타입과 같은 자료형도 반환할 수 있다. 즉, 더 넓은 범위를 반환할 수 있다.
아하!@Builder
나 생성자를 사용할 때는 반환형이 정해져 있거나, 한 필드만 수정하고 싶은데 다른 필드에 해당하는 코드까지 모두 작성해야 하거나, 다른 자료형으로 변환하여 반환하고 싶을 때 하나하나 작성해야 하는 단점이 있었다. 정적 팩토리 메서드는 이런 점에서 유리하다는 것이다. - 객체 생성을 캡슐화 할 수 있다.
일반적으로 생성자는 객체(내부의 필드들)를 초기화하면서 객체를 생성하는 역할을 한다. 하지만 정적 팩토리 메서드를 사용하면 생성자는 초기화하는 역할과 객체를 생성하는 역할을 분리할 수 있다고 한다.
여담으로, 이 내용(생성자 대신 정적 팩토리 메서드들을 사용하는 것을 고려해라)은 Effective Java의 Item 1이라고 한다. 🚩
정적 팩토리 메서드 in DTO
DTO 클래스에서 쓰일 수 있는 정적 팩토리 메서드들을 정리했다.
from
- Type-Conversion
- 하나의 인자를 받아서 인스턴스를 생성
- 엔티티 객체를 DTO로 변환할 때 사용
public class UserDTO { private String name; private int age; // 생성자는 private! private UserDTO(String name, int age) { this.name = name; this.age = age; } // 데이터 변환 public static UserDTO from(UserEntity userEntity) { return new UserDTO(userEntity.getName(), userEntity.getAge()); } }
of
- 여러 개의 인자를 받아서 인스턴스를 생성
- 객체를 재사용할 때 유리
public class ProductDTO { private String productName; private double price; // 생성자 private ProductDTO(String productName, double price) { this.productName = productName; this.price = price; } // 객체 생성 public static ProductDTO of(String productName, double price) { return new ProductDTO(productName, price); } }
정적 팩토리 메서드 in Java
Java에서 지원하는(그동안 정적 팩토리 메서드인지도 모르고 쓴 😅) 정적 팩토리 메서드들을 정리했다.
Integer, String, Date-Time
from
과of
에 비해 더 다양하게 쓰일 수 있음Integer/String 등등.valueOf();
에 쓰이는 그 valueOf() 라고 한다. 👀
Integer.valueOf(...); String.valueOf(...);
Optional
- 얘도 정적 팩토리 메서드를 사용한 것이라고 한다!
Optional<String> value1 = Optional.empty(); Optional<String> value2 = Optional.of("Example"); Optional<String> value3 = Optional.ofNullable(null);
newInstance
- 앞서 장점 3번의 내용에 해당하는 메서드로, 인스턴스 생성을 캡슐화할 수 있는 메서드다. 아래처럼 쓸 수 있다.
Array.newInstance(classObject, length);
결론
이때까지 @Builder
와 생성자만 활용했기 때문에, 정적 팩토리 메서드는 한 번도 사용하지 않았었다. 하지만, Effective Java에서 Item 1로 강조하고 있고, 위 내용은 반드시 알아야 하는 내용이라고 여러 곳에서 강조하고 있어 개인적으로 진행하고 있는 토이 프로젝트에서부터 적용하는 연습을 해봐야겠다! 😄