TODO: отвалидировать – текст собран автоматически из материалов курса на Google Drive, проверьте формулировки и код.
Создавать объекты должен тот класс, который эти объекты преимущественно использует: агрегирует их или вызывает их методы.
Кто должен порождать объект
Объект A должен порождать объект B, если выполняется хотя бы одно:
- A содержит или агрегирует объекты B – держит их как свойство или коллекцию;
- A активно использует объекты B – основной объём работы с B идёт через A;
- A обладает данными инициализации B – при каждом создании B данные берутся из A.
public class Order
{
private readonly List<OrderItem> _items = new();
// Заказ агрегирует позиции и знает данные для их создания –
// значит, он же их и создаёт
public void AddItem(Product product, int quantity)
{
_items.Add(new OrderItem(product, quantity, product.Price));
}
}
class Order {
public:
// Заказ агрегирует позиции и знает данные для их создания –
// значит, он же их и создаёт
void AddItem(const Product& product, int quantity) {
items_.emplace_back(product, quantity, product.price);
}
private:
std::vector<OrderItem> items_;
};
type Order struct {
items []OrderItem
}
// Заказ агрегирует позиции и знает данные для их создания –
// значит, он же их и создаёт
func (o *Order) AddItem(product Product, quantity int) {
o.items = append(o.items, OrderItem{
Product: product,
Quantity: quantity,
Price: product.Price,
})
}
class Order:
def __init__(self) -> None:
self._items: list[OrderItem] = []
# Заказ агрегирует позиции и знает данные для их создания –
# значит, он же их и создаёт
def add_item(self, product: Product, quantity: int) -> None:
self._items.append(OrderItem(product, quantity, product.price))
class Order {
private readonly items: OrderItem[] = [];
// Заказ агрегирует позиции и знает данные для их создания –
// значит, он же их и создаёт
addItem(product: Product, quantity: number): void {
this.items.push(new OrderItem(product, quantity, product.price));
}
}
public class Order {
private final List<OrderItem> items = new ArrayList<>();
// Заказ агрегирует позиции и знает данные для их создания –
// значит, он же их и создаёт
public void addItem(Product product, int quantity) {
items.add(new OrderItem(product, quantity, product.getPrice()));
}
}
class Order {
private val items = mutableListOf<OrderItem>()
// Заказ агрегирует позиции и знает данные для их создания –
// значит, он же их и создаёт
fun addItem(product: Product, quantity: Int) {
items += OrderItem(product, quantity, product.price)
}
}
Связь с другими принципами
Creator сочетается с Information Expert и с Low Coupling: знать об объектах должен только тот, кто их использует.
При этом принцип не сочетается с концепцией Dependency Injection, при которой многие объекты создаются при старте приложения, а затем внедряются друг в друга DI-механизмом. Это не противоречие, а разные слои: доменные объекты обычно создаёт Creator, а сервисы – контейнер.