복잡한 객체 생성을 맡길 수 있는 '팩토리 패턴'
팩토리는 객체를 만드는 지식에 특화된 객체다. 객체를 생성하기 위해 때로는 복잡한 생성과정에 대해서 알아야할 필요가 있을 것이다. 객체 생성 과정 자체를 별도의 객체를 만들어 두면 코드의 의도를 더 명확하게 할 수 있고, 클라이언트에의 코드는 단순하게 만들 수 있다. 도구를 만드는 것과 도구를 사용하는 것이 전혀 별개의 지식이듯이 객체를 생성하는 책임을 모델을 나타내기 위한 객체에 맡기는 것은 어울리지 않는다. 생성을 팩토리 객체에 위임하자.
팩토리의 목적
- 도메인 생성 과정과 관련된 지식을 위임 받는다.
- 클라이언트(서비스 레이어)에서 도메인 객체 인스턴스를 생성하는 코드가 간결해 진다.
- 도메인 생성 과정에 필요한 의존성을 도메인 객체에서 분리할 수 있다.
public class UserApplicationService
{
public Task CreateUser(CreateUserCommand command)
{
UserId newUserId = _userRepository.GetNewId();
User user = new User(
newUserId,
new UserName(command.UserName),
new Email(command.UserName),
new PhoneNumber(command.PhoneNumber),
command.Cars?.Select(car => new Car(
command.CarNo,
command.CarName,
command.ModelNo)),
command.UserRole?.Select(role => new UserRole(
role.RoleId)),
...
);
await _userRepository.Save(user);
}
}
public class UserApplicationService
{
private readonly IUserFactory _userFactory;
...
public Task CreateUser(CreateUserCommand command)
{
var user = _userFactory.CreateUser();
await _userRepository.Save(user);
}
}
public class UserFactory
{
private readonly IUserRepository _userRepository;
public UserFactory(IUserRepository userRepository)
=> _userRepository = userRepository;
public User CreateUser(CreateUserCommand command)
{
UserId newUserId = _userRepository.GetNewId();
return new User(
newUserId,
new UserName(command.UserName),
new Email(command.UserName),
new PhoneNumber(command.PhoneNumber),
command.Cars?.Select(car => new Car(
command.CarNo,
command.CarName,
command.ModelNo)),
command.UserRole?.Select(role => new UserRole(
role.RoleId)),
...
);
}
}
어떠한 경우에 사용해야할까?
- 팩토리 패턴을 무조건 사용해야 하는 것은 아니다. 도메인 객체 내부에 팩토리 메서드 패턴을 적용해도 되고, 생성자를 이용해 서비스에서 직접 인스턴스를 생성해줘도 된다.
- 객체 생성에 다른 의존성이 필요한 경우
- DB에서 새로운 Id를 구한다거나, 시퀀스를 구한다거나
- 도메인 모델과 퍼시스턴스 모델이 명확히 분리된 경우
- 도메인 객체의 멤버변수가 많은 경우
- 인스턴스를 생성하는 너무 길어져서 코드를 숨기고 싶은 경우, 팩토리 생성 후 생성 메서드의 매개변수도 Command 객체를 활용할 수 있다.
- 상속과 다형성이 고려되어야 할 경우
반응형
'서적 > 도메인 주도 설계 철저 입문' 카테고리의 다른 글
[도메인주도설계철저입문] 7장 소프트웨어의 유연성을 위한 의존 관계 제어 (0) | 2024.03.14 |
---|---|
[도메인주도설계철저입문] 6장 애플리케이션 서비스 (0) | 2024.03.03 |
[도메인주도설계철저입문] 5장 리포지토리 (0) | 2023.10.16 |
[도메인주도설계철저입문] 4장 도메인 서비스 (0) | 2023.10.16 |
[도메인주도설계철저입문] 3장 도메인 엔티티 (0) | 2023.10.15 |
복잡한 객체 생성을 맡길 수 있는 '팩토리 패턴'
팩토리는 객체를 만드는 지식에 특화된 객체다. 객체를 생성하기 위해 때로는 복잡한 생성과정에 대해서 알아야할 필요가 있을 것이다. 객체 생성 과정 자체를 별도의 객체를 만들어 두면 코드의 의도를 더 명확하게 할 수 있고, 클라이언트에의 코드는 단순하게 만들 수 있다. 도구를 만드는 것과 도구를 사용하는 것이 전혀 별개의 지식이듯이 객체를 생성하는 책임을 모델을 나타내기 위한 객체에 맡기는 것은 어울리지 않는다. 생성을 팩토리 객체에 위임하자.
팩토리의 목적
- 도메인 생성 과정과 관련된 지식을 위임 받는다.
- 클라이언트(서비스 레이어)에서 도메인 객체 인스턴스를 생성하는 코드가 간결해 진다.
- 도메인 생성 과정에 필요한 의존성을 도메인 객체에서 분리할 수 있다.
public class UserApplicationService
{
public Task CreateUser(CreateUserCommand command)
{
UserId newUserId = _userRepository.GetNewId();
User user = new User(
newUserId,
new UserName(command.UserName),
new Email(command.UserName),
new PhoneNumber(command.PhoneNumber),
command.Cars?.Select(car => new Car(
command.CarNo,
command.CarName,
command.ModelNo)),
command.UserRole?.Select(role => new UserRole(
role.RoleId)),
...
);
await _userRepository.Save(user);
}
}
public class UserApplicationService
{
private readonly IUserFactory _userFactory;
...
public Task CreateUser(CreateUserCommand command)
{
var user = _userFactory.CreateUser();
await _userRepository.Save(user);
}
}
public class UserFactory
{
private readonly IUserRepository _userRepository;
public UserFactory(IUserRepository userRepository)
=> _userRepository = userRepository;
public User CreateUser(CreateUserCommand command)
{
UserId newUserId = _userRepository.GetNewId();
return new User(
newUserId,
new UserName(command.UserName),
new Email(command.UserName),
new PhoneNumber(command.PhoneNumber),
command.Cars?.Select(car => new Car(
command.CarNo,
command.CarName,
command.ModelNo)),
command.UserRole?.Select(role => new UserRole(
role.RoleId)),
...
);
}
}
어떠한 경우에 사용해야할까?
- 팩토리 패턴을 무조건 사용해야 하는 것은 아니다. 도메인 객체 내부에 팩토리 메서드 패턴을 적용해도 되고, 생성자를 이용해 서비스에서 직접 인스턴스를 생성해줘도 된다.
- 객체 생성에 다른 의존성이 필요한 경우
- DB에서 새로운 Id를 구한다거나, 시퀀스를 구한다거나
- 도메인 모델과 퍼시스턴스 모델이 명확히 분리된 경우
- 도메인 객체의 멤버변수가 많은 경우
- 인스턴스를 생성하는 너무 길어져서 코드를 숨기고 싶은 경우, 팩토리 생성 후 생성 메서드의 매개변수도 Command 객체를 활용할 수 있다.
- 상속과 다형성이 고려되어야 할 경우
반응형
'서적 > 도메인 주도 설계 철저 입문' 카테고리의 다른 글
[도메인주도설계철저입문] 7장 소프트웨어의 유연성을 위한 의존 관계 제어 (0) | 2024.03.14 |
---|---|
[도메인주도설계철저입문] 6장 애플리케이션 서비스 (0) | 2024.03.03 |
[도메인주도설계철저입문] 5장 리포지토리 (0) | 2023.10.16 |
[도메인주도설계철저입문] 4장 도메인 서비스 (0) | 2023.10.16 |
[도메인주도설계철저입문] 3장 도메인 엔티티 (0) | 2023.10.15 |