Course program← Объектно ориентированное программирование
1История ООП
2Объект и Класс
3Базовые концепции ООП
4Принцип проектирования GRASP
5Принцип проектирования SOLID
6Паттерны GOF
7Методические материалы

Creator

This lesson was translated automatically – it may contain errors.

Objects should be created by the class that mostly uses them: aggregates them or calls their methods.

Who should create the object

Object A should create object B if at least one of these holds:

  • A contains or aggregates B objects – keeps them as a property or a collection;
  • A actively uses B objects – the bulk of the work with B goes through A;
  • A holds B’s initialisation data – every time a B is created the data comes from A.
public class Order
{
    private readonly List<OrderItem> _items = new();

    // The order aggregates the items and knows the data to create them –
    // so it is the one that creates them
    public void AddItem(Product product, int quantity)
    {
        _items.Add(new OrderItem(product, quantity, product.Price));
    }
}
class Order {
public:
    // The order aggregates the items and knows the data to create them –
    // so it is the one that creates them
    void AddItem(const Product& product, int quantity) {
        items_.emplace_back(product, quantity, product.price);
    }

private:
    std::vector<OrderItem> items_;
};
type Order struct {
	items []OrderItem
}

// The order aggregates the items and knows the data to create them –
// so it is the one that creates them
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] = []

    # The order aggregates the items and knows the data to create them –
    # so it is the one that creates them
    def add_item(self, product: Product, quantity: int) -> None:
        self._items.append(OrderItem(product, quantity, product.price))
class Order {
    private readonly items: OrderItem[] = [];

    // The order aggregates the items and knows the data to create them –
    // so it is the one that creates them
    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<>();

    // The order aggregates the items and knows the data to create them –
    // so it is the one that creates them
    public void addItem(Product product, int quantity) {
        items.add(new OrderItem(product, quantity, product.getPrice()));
    }
}
class Order {
    private val items = mutableListOf<OrderItem>()

    // The order aggregates the items and knows the data to create them –
    // so it is the one that creates them
    fun addItem(product: Product, quantity: Int) {
        items += OrderItem(product, quantity, product.price)
    }
}

Relation to the other principles

Creator goes together with Information Expert and Low Coupling: only the one that uses the objects should know about them.

What it does not go together with is dependency injection, where many objects are created at application start-up and then injected into each other by a DI mechanism. That is not a contradiction but different layers: domain objects are usually created by a Creator, services – by the container.