Агрегация
Отношение агрегации между классами имеет непосредственное отношение к агрегации между их экземплярами.
Пример. Вернемся к классу Controller, который является абстракцией объектов, управляющих температурой в теплице (см. разд. 3.4).
Класс Controller – это целое, а экземпляр класса Heater (нагреватель) – одна из его частей. В рассмотренном случае мы имеем специальный случай агрегации – композицию.
Композиция – форма агрегирования, в которой целое владеет своими частями, имеющими одинаковое с ним время жизни. Части с нефиксированной кратностью могут быть созданы после создания агрегата, но, будучи созданными, живут и умирают вместе с ним. Такие части могут также быть явно удалены перед уничтожением агрегата. В случае композитного агрегирования объект в любой момент времени может быть частью только одного композита.
С точки зрения реализации в языке С++ композиция может быть осуществлена включением атрибута-части в класс-агрегат по значению, как это сделано в примере, приведенном в разд. 3.4. Менее обязывающим является включение по ссылке. Мы могли бы изменить описание атрибута h класса Controller:
Heater * h;
В этом случае класс Controller по-прежнему означает целое, но его часть, экземпляр класса Heater, содержится в целом косвенно. Теперь объекты живут отдельно друг от друга: мы можем создавать и уничтожать экземпляры классов независимо.
Агрегация является направленным отношением. Объект Heater входит в объект Controller, а не наоборот. Физическое вхождение одного в другое нельзя «зациклить», а указатели – можно (каждый из двух объектов может содержать указатель на другой).
Пример. Пусть управление температурой каждый объект класса Controller осуществляет в соответствии с задаваемым ему планом. План представим в виде экземпляра класса Plan.
class Plan;
class Controller{
...
void process(Plan&);
...
};
Класс Plan упомянут как часть описания функции-члена process; это дает нам основание сказать, что класс Controller пользуется услугами класса Plan.
Отношение зависимости (использования) между классами означает, что изменение в спецификации одного класса может повлиять на другой класс, который его использует, причем обратное в общем случае неверно. Можно сказать, что один из классов (клиент) пользуется услугами другого (сервера).
Один класс может использовать другой по-разному. В нашем примере это происходит при описании интерфейсной функции. Отношение использования также имеет место, если в реализации какой-либо операции происходит объявление локального объекта используемого класса.