정적 팩토리 메서드를 활용하면 생성 목적에 대해 이름지을 수도 있고, 객체의 생성을 제어할 수 있다.
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ChatRoom {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "chatRoom_id")
private Long id;
@OneToMany(mappedBy = "room", cascade = CascadeType.ALL)
private List<ChatRoomUser> userList;
private ChatRoom(List<ChatRoomUser> userList) {
this.userList = userList;
}
public static ChatRoom from(List<ChatRoomUser> userList) {
return new ChatRoom(userList);
}
}
구현하고 있는 것은 채팅시스템의 채팅 방 엔티티 코드이다.
당장 필요한 것은 방의 사용자 리스트뿐이기에 이렇게 private 생성자를 만들어두고 from 메서드로 새로운 객체를 반환하는 식으로 사용할 수도 있다.
from 메서드는 public으로 열려있기에 다른 곳에서도 호출이 가능하다.
이렇게 객체의 생성을 제어할 수 있다.
private ChatRoom(List<ChatRoomUser> userList, String roomName, Long adminId, LocalDateTime createdAt) {
this.userList = userList;
this.roomname = roomName;
this.adminId = adminId;
this.createdAt = createdAt;
}
public static ChatRoom of(List<ChatRoomUser> userList, String roomName, Long adminId, LocalDateTime createdAt ) {
return new ChatRoom(userList, roomName, adminId, createdAt);
}
예를 들기 위해 세 가지 필드를 추가해보았다. 매개변수가 늘어났기에 메서드 이름이 from에서 of로 변했다 (참고한 블로그 참조). 만일 필드 수가 무한정 추가된다면 실수 위험이 커진다.
@Builder(access = AccessLevel.PRIVATE)
private ChatRoom(List<ChatRoomUser> userList, String roomName, Long adminId, LocalDateTime createdAt){
this.userList = userList;
this.roomName = roomName;
this.adminId = adminId;
this.createdAt = createdAt;
}
public static ChatRoom createChatRoom(List<ChatRoomUser> userList, String roomName, Long adminId, LocalDateTime createdAt){
return ChatRoom.builder()
.userList(userList)
.roomName(roomName)
.adminId(adminId)
.createdAt(createdAt)
.build();
}
도메인의 필드가 늘어나는 확장성을 고려해서 정적 팩토리 메서드에 builder 패턴을 새로운 메서드를 만들어 사용하면 순서 실수할 일 없이 사용할 수 있다.
도메인의 필드 수가 적다면 단순히 정적 팩토리 메서드로 충분하겠지만, 프로젝트를 하다보면 필드 수가 끝도 없이 늘어날 수 있기에 이렇게 미리 빌더 패턴으로 확장성을 챙겨가는 것도 좋은 방법인 것 같다!