정적 팩토리 메서드 패턴( Static Factory Method )
。자바 클래스내객체 생성자를 간접적으로 호출하여객체를 생성하는static으로 선언된메서드
▶클라이언트에게객체 생성과정을캡슐화하여 내부구현을 외부로부터 숨길 수 있다.
。Map.of()등의메서드도정적 팩토리 메서드 패턴을 기반으로 구현
。정적 팩토리 메서드 패턴사용 시생성자를private로 설정함으로써생성자를 통한 생성을 차단
정적 팩토리 메서드는외부가 아닌,도메인이 스스로객체 생성을 주도
。기존@Builder 어노테이션을 비롯한생성자를 통한객체 생성은외부( ex.Service Layer)에서 주도하므로,DDD에 적합하지 않음.
。클래스 객체를 수신 시 다른객체로 수정하여 반환하는로직을Entity 클래스내 작성함으로써도메인 외부에서생성을 주도하지 않고,도메인 내부에서생성을 주도
▶ 주로Entity를인자로 받으면DTO로 반환하는로직을 작성함으로써사용자가Entity 간 매핑을 고려하지 않도록 설정이 가능
。 내부에검증용방어 로직을 작성함으로써도메인스스로검증이 가능public static MemberDetails from(Member member){ if (member == null) throw new IllegalArgumentException("멤버를 찾지 못함"); return MemberDetails.builder() .name(member.getName()) .email(member.getEmail()) .build() .setId(member.getId()) .setRole(member.getRole()); }
생성자와 달리메서드명을 임의로 설정할 수 있음
。메서드명으로 어떤생성 & 변환 패턴인지 유추할 수 있도록 다음 관례를 추종해야한다
。객체를 생성하면서 동시에 실행해야할logic을 동시에 정의가 가능// ResponseEntity를 생성하는 정적 팩토리 메서드 public static ResponseEntity<String> of(HttpStatus status, String code) { return ResponseEntity.status(status).body(code); }public static <T> ApiResult<T> of(String code, String message, T data){ return new ApiResult<>(code,message,data); }。
데이터 요소를 포함하는객체를 생성하므로of()로 명명
▶<T>: 해당메서드에서Generic을 사용을 위해 명시하는 선언부
정적 팩토리 메서드 패턴유형
DB Entity를DB에서 가져오고클라이언트에게 반환 시 민감정보를 제외한DTO를 생성시에도 활용
。클라이언트에게DB Entity 객체반환 시연관관계 객체등 모든field를 포함해서 반환하면 안되므로public static Details of(MemberEntity memberEntity){ return new Details( memberEntity.getLoginId(), memberEntity.getName(), memberEntity.getEmail() ); }
객체 생성시 동시에 수행해야할 추가작업을 정의 시 활용
ex )DB Entity 객체생성 시 동시에연관관계에서부모 Entity의@OneToMany List<> 필드에 추가할 필요가 있을때정적 팩토리 메서드사용// 자식 Entity 이므로 외래키 Field에 @ManyToOne을 선언 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="memberId") // DB Table의 외래키 field명 설정 private MemberEntity member; // 캡슐화된 생성자 private OrderEntity(Receiver receiver, LocalDateTime deliveredAt, MemberEntity member, OrderStatus orderStatus) { this.receiver = receiver; this.deliveredAt = deliveredAt; this.member = member; this.orderStatus = orderStatus; } // 정적 팩토리 메서드 public static OrderEntity of(Receiver receiver, MemberEntity member){ var order = new OrderEntity( receiver, LocalDateTime.now().plusDays(3), member, OrderStatus.PENDING ); member.mapToOrder(order); // 부모 Entity 객체에 생성된 OrderEntity객체 추가 return order; }
정적 팩토리 메서드명의관례
。메서드명으로 어떤생성 & 변환 패턴인지 유추할 수 있도록 다음 관례를 추종해야한다
of(요소1 , ...):
。복수의데이터요소를 받아서객체를 생성하여 반환하는경우 사용하는메소드명
ex )Map.of(1,2,3, ...)
from():
。변환용도로 입력된객체를 전달받아객체를 생성하여 반환 시 사용하는메소드명
ex )YearMonth.from(LocalDate.of(2023, 6, 20))
valueOf(요소):
。변환용도로 입력된값을 다른Type의값으로 변환하여 반환 시 사용하는메소드명
ex )String.valueOf(1)