Композиция - это когда object Aсодержит object Bи object Aтакже несет ответственность за создание object B.
Композиционные отношения
У нас есть класс A, который будет использоваться классом B.
final class A
{
}
Есть несколько вариантов того, как может выглядеть композиция.
Прямая инициализация композиции:
final class B
{
private $a = new A();
}
Состав инициализации конструктора
final class B
{
private $a;
public function __construct()
{
$this->a = new A();
}
}
Ленивая инициализация композиции
final class B
{
private $a = null;
public function useA()
{
if ($this->a === null) {
$this->a = new A();
}
/* Use $this->a */
}
}
Вы видите, что это создает тесные отношения между классами Aи B. Класс Bпросто не может существовать без A. Это огромное нарушение принципа внедрения зависимостей , которое гласит:
Зависимость - это объект, который можно использовать (сервис). Инъекция - это передача зависимости зависимому объекту (клиенту), который будет ее использовать. Услуга является частью состояния клиента. Передача сервиса клиенту, а не предоставление клиенту возможности создавать или находить сервис, является фундаментальным требованием шаблона.
Композиция иногда имеет смысл, например, вызов new DateTime в php или new std::vector<int>в C ++. Но чаще всего это предупреждение о том, что ваш код написан неправильно.
В случае, когда class A будет специальным объектом, используемым для кэширования, class Bон всегда будет кэшироваться с использованием реализации class A, и у вас не будет контроля для его динамического изменения, что плохо.
Кроме того, если вы использовали ленивую композицию инициализации , то есть у вас есть рабочий object B, называемый useA()методом и созданиемobject A не удастся, ваш файл object Bвнезапно окажется бесполезным.
Агрегация, с другой стороны, является способом взаимоотношений, который следует принципу DI . object Bнеобходимо использовать object A, то вы должны передать уже созданный экземпляр object Aдляobject B , и если создание object Aзавершится ошибкой, ничего не будет передано в первую очередь.
Короче, Агрегация - это представление UML для принципа внедрения зависимостей , будь то внедрение конструктора, установка сеттера или внедрение открытого свойства.
Это все агрегации
Самая тесная инъекция в конструктор ( object Bне может существовать без object A).
final class B
{
private $a;
public function __construct(A $a)
{
$this->a = $a;
}
}
Слабее (вы можете или не можете использовать object Aвнутри object B, но если вы это сделаете, вы, вероятно, должны установить его первым).
Через сеттер:
final class B
{
private $a;
public function setA(A $a)
{
$this->a = $a;
}
}
Через общественную собственность:
final class B
{
public $a;
}
На самом деле нет хорошего способа оправдать использование Aggregation over Composition, если все, что вы используете, - это конкретные реализации классов, но как только вы начнете внедрять интерфейсы или в случае абстрактных классов C ++, внезапно Aggregation станет единственным способом выполнить ваш контракт.