팩토리 패턴 1. 기본 생성자는 private
기본 생성자를 private으로 선언한다. 이렇게 하는 이유는 객체 생성을 팩토리를 통해서만 하도록 통제하기 위해서이다. 이때 주의해야 할 점은 기본 생성자를 아예 만들지 않으면 자바 컴파일러가 자동으로 기본 생성자를 생성하여 누구나 기본 생성자를 통한 User 생성할 수 있게 된다는 것이다. 따라서 생성자를 반드시 만들고, private으로 설정하는 것이 바람직하다.
package com.woojoovove.ddd11.user.domain;
public class User {
private final UserId id;
private UserName name;
private User(UserId id, UserName name) {
if (id == null) throw new IllegalArgumentException("id cannot be null");
if (name == null) throw new IllegalArgumentException("name cannot be null");
this.id = id;
this.name = name;
}
}
팩토리 패턴 2. 팩토리 인터페이스 선언
팩토리를 다음`IUserFactory`와 같이 인터페이스로 선언한다. 이렇게 하는 이유는
1. 객체를 생성할 때 디폴트로 전/후 처리가 필요한 경우에 인터페이스의 디폴트 메서드에 구현이 가능함.
2. 객체를 생성하는 여러 가지 방법을 인터페이스의 구현 클래스가 자유롭게 정의할 수 있게 함으로써 확장성을 높이기 위함이다.
예를 들어 객체 하나를 생성하기 위해 DB에 접근하는 팩토리와, 비즈니스 로직 테스트를 위해 DB를 띄우지 않는 `InMemoryFactory`가 둘 다 필요할 때는 각각 인터페이스의 구현 클래스를 선언하면 된다.
package com.woojoovove.ddd11.user.domain;
public interface IUserFactory {
User create(UserName userName);
}
팩토리 패턴 3. Entity에 정적 팩토리 메소드를 구현
다음 `create()`와 같이 Entity를 생성하는 정적 팩토리 메소드를 구현한다. Entity의 인스턴스가 없어도 사용할 수 있도록 정적(`static`) 메소드로 선언하며, 외부에서 사용할 수 있도록 `public`으로 열어둔다. 마지막으로 객체를 immutable하게 관리하기 위해서 `final` 키워드를 붙인다.
package com.woojoovove.ddd11.user.domain;
public class User {
private final UserId id;
private UserName name;
private User(UserId id, UserName name) {
if (id == null) throw new IllegalArgumentException("id cannot be null");
if (name == null) throw new IllegalArgumentException("name cannot be null");
this.id = id;
this.name = name;
}
public static final User create(UserId id, UserName name) {
return new User(id, name);
}
}
팩토리 패턴 4. 팩토리 인터페이스의 구현 클래스를 선언
다음은 `InMemoryUserFactory`이다. Entity의 `create()`를 사용하여 객체를 생성하고 반환한다. 테스트를 위한 InMemory 생성자로서 `UUID.randomUUID()`를 활용하여 id를 생성할 수 있게 구현하였다. 운영에서 사용할 RealUserFactory는 동일한 방식으로 `IUserFactory`를 다르게 구현할 수 있다.
package com.woojoovove.ddd11.user.domain;
import java.util.UUID;
public class InMemoryUserFactory implements IUserFactory {
@Override
public User create(UserName userName) {
UserId id = new UserId(UUID.randomUUID().toString());
return User.create(id, userName);
}
}
'DDD > 도메인 주도 설계 철저 입문' 카테고리의 다른 글
테스트 커버리지 높이는 법 - 「도메인 주도 설계 철저 입문」 11장 (3) (1) | 2024.12.11 |
---|---|
엔티티 중복 확인은 도메인 서비스인가 앱 서비스인가 - 「도메인 주도 설계 철저 입문」 11장 (3) (2) | 2024.12.10 |
DDD 프로젝트 폴더 구조 - 「도메인 주도 설계 철저 입문」 11장 (1) (1) | 2024.11.20 |
데이터의 무결성 유지하기 - 「도메인 주도 설계 철저 입문」 10장 (0) | 2024.10.21 |
팩토리 패턴 - 「도메인 주도 설계 철저 입문」 9장 (0) | 2024.10.13 |