Алгоритмы

Просто о композиции, агрегации и ассоциации в JavaScript

Spread the love

Данная небольшая заметка о типах отношений между объектами в ООП. Можно использовать как шпаргалку, если кто знал, но подзабыл или, если для кого эти термины будут в новинку используйте как первый шаг в изучение основ ООП.

Композиция, агрегация и ассоциация — все эти термины или точнее парадигмы ООП про отношения между объектами или классами между собой. Всего существует пять основных типов отношений:
Ассоциация
Агрегарция
Композиция
и еще два типа, которые в этой статье рассматривать не будем:
Наследования (иногда этот тип еще называют генерализацией)
Реализация (это тип отношений базируется на интерфейсах. То есть создается интерфейсы, которые основной класс должен реализовать.)

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

Самый простой способ понять эти термины это использовать аналогию из реального мира. Представим себе что у нас есть класс комната и есть два других класса мебель и стена. Мы можем сказать что у комнаты будет какая та мебель и какие то стены. То есть объект комната может использоваться объекты стены и мебель по мере необходимости. Но есть разница в отношения комната — стены и комната — мебель. Разница в том что стены никогда не выйдут из объекта комната. Стены не могут существовать вне комнаты. То есть стена всегда будет создаваться внутри объекта комната. Такая связь называется композиция. И эта связь будет жесткой. Зато мебель очень легко представить за пределами комнаты. Один экземпляр мебели может принадлежать с начало одной комнате потом другой. Такая связь называется ассоциацией или агрегацией. И такая связь будет более гибкой. О различие между ассоциацией или агрегацией чуть позже.

Способ реализации отношений между классами или объектами и есть основное концептуальное различие между композицией, агрегацией и ассоциацией . При композиции мы не можем что то вынести а при агрегации или ассоциации мы можем передать объект из одного объекта в другой.

Рассмотрим эти связи подробнее.

Ассоциация

Ассоциация это такой тип при котором объекты будут ссылаться друг на друга. При этом они остаются полностью независимыми друг от друга.

Пример реализации ассоциации

class Logger {
  constructor() {
    this.stream = null;
  }
  log(message) {
    if (this.stream) {
      this.stream.write(message);
    }
  }
}

const logger = new Logger();
logger.stream = process.stdout;
logger.log('Here we are');

Тут у нас есть атрибут stream, в котором должна быть ссылка на поток который куда то будет отправлять сообщение. Метод log проверяет что в классе задан stream и использует его для отправки сообщения. То есть ассоциация это когда у одного класса есть ссылка на другой класс. Это создает большую гибкость в отношениях между классами. Например у нас есть возможность смены потока во время выполнения программы.

Агрегация

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

Пример реализации агрегации:

class Logger {
  constructor(stream) {
    this.stream = stream;
  }
  log(message) {
    if (this.stream) {
      this.stream.write(message);
    }
  }
}

const logger = new Logger(process.stdout);
logger.log('Here we are');

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

Композиция

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

Пример реализации композиции

const fs = require('fs')

class Logger {
  constructor(name) {
    this.stream = fs.createWriteStream(name);
  }
  log(message) {
    this.stream.write(message);
  }
}

const logger = new Logger('file.log');
logger.log('Here we are');

В данном случае внутри конструктора создается экземпляр другого класса. При этом создается более крепкая связанность этих двух классов. То есть класс Logger обязательно знает что существует библиотека fs, у него есть класс fs и у него есть метод createWriteStream и т. д. Он полностью знает реализацию другого класса.

То есть в ассоциации и агрегации предполагалось что эти два класса создается независимо, а потом связываются ссылками, в композиции они создается вместе в момент вызова конструктора.

Источники для статьи:
Ассоциация, агрегация и композиция объектов в JavaScript
Агрегация и Композиция

Практические вопросы на проверку понимания

Была ли вам полезна эта статья?
[50 / 4.7]

Spread the love
DenSP

View Comments

  • Вопрос по типам отношений Ассоциация и Агрегация. У вас в примере в случае Ассоциации класс Logger имеет поле stream с ссылкой на объект "stdout" и в случае Агрегации в вашем примере класс Logger имеет поле stream с ссылкой на объект "stdout". В чем тут разница?

  • Примеры непонятны. Описание хорошее, а примеры полная херня.

  • Дважды: pay, pay. Это опечатка?
    Employee::constructor(name, age, pay, pay)

    • Да была опечатка. Спасибо, поправил.

  • добавь плиз схему как это будет выглядеть в UML. Спасибо!

  • Классный пример!!! просто огонь! всё понял сразу, правда я уже прочитал 8 главу в книге Вайсфилда( ООП мышление ), несколько статей и только когда были примеры на моём любимом JavaScript-e я всё смог понять

    композиция - это когда мы создаём экземпляр объекта в конструкторе (тут всё просто)

    агрегация - это когда мы кладём объект в момент создания экземпляра класса типо 
    new Obj(new SomeObj())

    ассоциация - это когда мы можем изменять класс с которым мы взаимодействуем в процессе работы объекта, мне не совсем понравился пример автора там где он без интерфейса работает с объектом на прямую к свойству, это не по ООП-шному, по этому я сделал следующий пример
    obj.setAssociation(new Object());
    obj.getAssociation().someMethod();

    obj.setAssociation(new SomeObj());
    obj.getAssociation().someMethod();

  • привет, не могли вы объяснить, почему не выводится в консоль данную строку (агрегация).

    'use strict';

    class Salary {

    constructor(pay, bonus) {

    this.pay = pay;

    this.bonus = bonus;

    }

    annualSalary() {

    return (this.pay * 12) + this.bonus;

    }

    }

    class Employee {

    constructor(name, age, salary) {

    this.name = name;

    this.age = age;

    this.salary = salary;

    }

    totalSalary() {

    if (this.salary) {

    return this.salary.annualSalary();

    }

    }

    }

    let salary = new Salary(15000, 10000);

    let emp = Employee('Max', 25, salary);

    console.log(emp.totalSalary());

    Class constructor Employee cannot be invoked without 'new'

    но когда пишу new то выводится 190000, и больше ничего.

  • Спасибо за статью! Узнал много полезного. Но обратите пожалуйста внимание на грамматику. Сложно читать текст с ошибками. Сбивает с мысли.

  • Один экземпляр мебели может принадлежать с начал!О!? одной комнате потом другой.
    Серьезно???? Что за школота писила?

Recent Posts

Vue 3.4 Новая механика v-model компонента

Краткий перевод: https://vuejs.org/guide/components/v-model.html Основное использование​ v-model используется для реализации двусторонней привязки в компоненте. Начиная с Vue…

11 месяцев ago

Анонс Vue 3.4

Сегодня мы рады объявить о выпуске Vue 3.4 «🏀 Slam Dunk»! Этот выпуск включает в…

11 месяцев ago

Как принудительно пере-отобразить (re-render) компонент Vue

Vue.js — это универсальный и адаптируемый фреймворк. Благодаря своей отличительной архитектуре и системе реактивности Vue…

2 года ago

Проблемы с установкой сертификата на nginix

Недавно, у меня истек сертификат и пришлось заказывать новый и затем устанавливать на хостинг с…

2 года ago

Введение в JavaScript Temporal API

Каким бы ни было ваше мнение о JavaScript, но всем известно, что работа с датами…

2 года ago

Когда и как выбирать между медиа запросами и контейнерными запросами

Все, кто следит за последними событиями в мире адаптивного дизайна, согласятся, что введение контейнерных запросов…

2 года ago