Просто о композиции, агрегации и ассоциации в 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
Агрегация и Композиция

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

1. Какой тип отношений?


class Salary {
	constructor(pay, bonus) {
		this.pay = pay;
		this.bonus = bonus;
	}

	annual_salary() {
		return (this.pay * 12) + this.bonus;
	}
}

class Employee {
	constructor(name, age, salary) {
		this.name = name;
		this.age = age;
		this.salary = salary;
	}

	total_salary() {
		if (this.salary) {
			return this.salary.annual_salary();
		}
	}
}

let salary = new Salary(15000, 10000)
let emp = Employee('Max', 25, salary)

console.log(emp.total_salary())
 
 
 

2. Какой тип отношений?


class Salary {
	constructor(pay, bonus) {
		this.pay = pay;
		this.bonus = bonus;
	}

	annual_salary() {
		return (this.pay * 12) + this.bonus;
	}
}

class Employee {
	constructor(name, age, pay, pay) {
		this.name = name;
		this.age = age;
		this.salary = new Salary(pay, pay);
	}

	total_salary() {
		return this.salary.annual_salary();
	}
}


let emp = Employee('Max', 25, 15000, 10000)
console.log(emp.total_salary())


 
 
 

3. Какой тип отношений?


class Salary {
	constructor(pay, bonus) {
		this.pay = pay;
		this.bonus = bonus;
	}

	annual_salary() {
		return (this.pay * 12) + this.bonus;
	}
}

class Employee {
	constructor(name, age) {
		this.name = name;
		this.age = age;
		this.salary = null;
	}

	total_salary() {
		if (this.salary) {
			return this.salary.annual_salary();
		}
	}
}

let emp = Employee('Max', 25)
emp.salary = new Salary(15000, 10000)
console.log(emp.total_salary())

 
 
 

Вопрос 1 из 3

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

Spread the love

Добавить комментарий

Ваш e-mail не будет опубликован.