← Назад к вопросам

В чем разница между агрегацией и композицией?

1.3 Junior🔥 221 комментариев
#ООП#SOLID и паттерны проектирования

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между агрегацией и композицией

Агрегация и композиция — это два вида связи (отношения) в объектно-ориентированном программировании, которые определяют, как один класс использует другой. Хотя они похожи, различие между ними критично для правильного проектирования архитектуры.

Композиция (HAS-A с强 связью)

Композиция — это отношение, когда один объект (контейнер) полностью владеет другим объектом (компонентом) и отвечает за его жизненный цикл. Если контейнер уничтожается, компонент тоже уничтожается.

public class Car {
    private Engine engine;
    private List<Wheel> wheels;
    
    public Car() {
        // Машина СОЗДАЁТ свой двигатель
        this.engine = new Engine();
        this.wheels = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            wheels.add(new Wheel());
        }
    }
    
    // Жизненный цикл частей зависит от жизненного цикла Car
    // Когда Car удаляется -> Engine и Wheels тоже удаляются
}

Характеристики композиции:

  • Сильная связь между объектами
  • Контейнер создаёт компонент
  • Компонент не может существовать без контейнера
  • Отношение один-ко-многим или один-к-одному
  • Пример: Car и Engine, Document и Page

Агрегация (HAS-A со слабой связью)

Агрегация — это отношение, когда один объект использует другой, но не владеет им полностью. Компонент может существовать независимо от контейнера, и их жизненные циклы разделены.

public class Department {
    private List<Employee> employees;
    
    // Отдел НЕ создаёт сотрудников
    // Сотрудники приходят и уходят независимо
    public void addEmployee(Employee emp) {
        employees.add(emp);
    }
    
    public void removeEmployee(Employee emp) {
        employees.remove(emp);
    }
    
    // Когда Department удаляется, Employee остаются живы
}

public class Company {
    public static void main(String[] args) {
        Employee emp1 = new Employee("John");
        Employee emp2 = new Employee("Jane");
        
        Department dept = new Department();
        dept.addEmployee(emp1);
        dept.addEmployee(emp2);
        
        // Даже если dept удалится, emp1 и emp2 остаются
    }
}

Характеристики агрегации:

  • Слабая связь между объектами
  • Контейнер НЕ создаёт компонент
  • Компонент может существовать независимо
  • Компонент может принадлежать нескольким контейнерам
  • Пример: Department и Employee, Team и Player

Сравнительная таблица

АспектКомпозицияАгрегация
СвязьСильная (HAS-A)Слабая (HAS-A)
Жизненный циклЗависимыйНезависимый
СозданиеКонтейнер создаётВнешний код создаёт
УдалениеУдаляется вместеСуществует отдельно
ПримерыCar→EngineDepartment→Employee

Диаграмма UML

Композиция (заполненный ромб):
Car ◆——— Engine
   ◆——— Wheel

Агрегация (пустой ромб):
Department ◇——— Employee

Практический пример на Java

// Композиция: House владеет Room
public class House {
    private List<Room> rooms;
    
    public House(int numberOfRooms) {
        rooms = new ArrayList<>();
        for (int i = 0; i < numberOfRooms; i++) {
            rooms.add(new Room()); // House создаёт Room
        }
    }
}

// Агрегация: Library содержит Book
public class Library {
    private List<Book> books; // Book существует независимо
    
    public Library() {
        books = new ArrayList<>();
    }
    
    public void addBook(Book book) {
        books.add(book); // Book создан снаружи
    }
}

Когда использовать что?

Композиция:

  • Когда компонент не имеет смысла без контейнера
  • Когда контейнер отвечает за создание и уничтожение
  • Когда требуется тесная связь
  • Пример: GUI форма и её элементы управления

Агрегация:

  • Когда компонент существует независимо
  • Когда нужна слабая связь
  • Когда компонент может быть переиспользован в других контейнерах
  • Пример: Работник может работать в разных проектах

Правильный выбор между композицией и агрегацией влияет на гибкость кода, его тестируемость и возможность повторного использования. В профессиональных проектах это одно из ключевых решений при проектировании классов.