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

Indirection (Перенаправление)

This lesson is not translated yet – the Russian original is below.

TODO: отвалидировать – текст собран автоматически из материалов курса на Google Drive, проверьте формулировки и код.

Перенаправление обеспечивает низкое зацепление между классами, назначая обязанности по их взаимодействию дополнительному объекту-посреднику.

Яркий пример – Controller из триады MVC: представление не обращается к модели напрямую.

// Прямая связь: каждый модуль знает про каждый
public class OrderModule
{
    private readonly WarehouseModule _warehouse = new();
    private readonly BillingModule _billing = new();
}

// Через посредника: модули знают только о нём
public class OrderCoordinator
{
    public void Place(Order order)
    {
        _warehouse.Reserve(order);
        _billing.Charge(order);
    }
}
// Прямая связь: каждый модуль знает про каждый
class OrderModule {
private:
    WarehouseModule warehouse_;
    BillingModule billing_;
};

// Через посредника: модули знают только о нём
class OrderCoordinator {
public:
    OrderCoordinator(IWarehouse& warehouse, IBilling& billing)
        : warehouse_(warehouse), billing_(billing) {}

    void Place(const Order& order) {
        warehouse_.Reserve(order);
        billing_.Charge(order);
    }

private:
    IWarehouse& warehouse_;
    IBilling& billing_;
};
// Прямая связь: каждый модуль знает про каждый
type OrderModule struct {
	warehouse *WarehouseModule
	billing   *BillingModule
}

// Через посредника: модули знают только о нём
type OrderCoordinator struct {
	warehouse Warehouse
	billing   Billing
}

func (c *OrderCoordinator) Place(order Order) error {
	if err := c.warehouse.Reserve(order); err != nil {
		return err
	}

	return c.billing.Charge(order)
}
# Прямая связь: каждый модуль знает про каждый
class OrderModule:
    def __init__(self) -> None:
        self._warehouse = WarehouseModule()
        self._billing = BillingModule()

# Через посредника: модули знают только о нём
class OrderCoordinator:
    def __init__(self, warehouse: Warehouse, billing: Billing) -> None:
        self._warehouse = warehouse
        self._billing = billing

    def place(self, order: Order) -> None:
        self._warehouse.reserve(order)
        self._billing.charge(order)
// Прямая связь: каждый модуль знает про каждый
class OrderModule {
    private readonly warehouse = new WarehouseModule();
    private readonly billing = new BillingModule();
}

// Через посредника: модули знают только о нём
class OrderCoordinator {
    constructor(
        private readonly warehouse: Warehouse,
        private readonly billing: Billing,
    ) {}

    place(order: Order): void {
        this.warehouse.reserve(order);
        this.billing.charge(order);
    }
}
// Прямая связь: каждый модуль знает про каждый
public class OrderModule {
    private final WarehouseModule warehouse = new WarehouseModule();
    private final BillingModule billing = new BillingModule();
}

// Через посредника: модули знают только о нём
public class OrderCoordinator {
    private final Warehouse warehouse;
    private final Billing billing;

    public OrderCoordinator(Warehouse warehouse, Billing billing) {
        this.warehouse = warehouse;
        this.billing = billing;
    }

    public void place(Order order) {
        warehouse.reserve(order);
        billing.charge(order);
    }
}
// Прямая связь: каждый модуль знает про каждый
class OrderModule {
    private val warehouse = WarehouseModule()
    private val billing = BillingModule()
}

// Через посредника: модули знают только о нём
class OrderCoordinator(
    private val warehouse: Warehouse,
    private val billing: Billing,
) {
    fun place(order: Order) {
        warehouse.reserve(order)
        billing.charge(order)
    }
}

Цена принципа

Посредник – это лишний уровень косвенности. Он снижает зацепление, но усложняет чтение: чтобы понять, что произойдёт, приходится идти по цепочке. Тот же компромисс подробно разбирается в паттерне Mediator.