Kompozycja ma miejsce, gdy object Azawiera object Bi object Ajest również odpowiedzialna za tworzenie pliku object B.
Relacja składu
Mamy klasę A, która będzie używana przez klasę B.
final class A
{
}
Istnieje wiele opcji, takich jak wygląd kompozycji.
Skład bezpośredniej inicjalizacji:
final class B
{
private $a = new A();
}
Kompozycja inicjalizacji konstruktora
final class B
{
private $a;
public function __construct()
{
$this->a = new A();
}
}
Leniwa kompozycja inicjalizacyjna
final class B
{
private $a = null;
public function useA()
{
if ($this->a === null) {
$this->a = new A();
}
/* Use $this->a */
}
}
Widzisz, tworzy to ścisły związek między klasami Ai B. Klasa Bpo prostu nie może istnieć bez A. Jest to ogromne naruszenie zasady wstrzykiwania zależności , która mówi:
Zależność to obiekt, z którego można korzystać (usługa). Zastrzyk to przekazanie zależności do obiektu zależnego (klienta), który go użyje. Usługa jest częścią stanu klienta. Podstawowym wymaganiem wzorca jest przekazanie usługi klientowi, zamiast umożliwienia klientowi zbudowania lub znalezienia usługi.
Kompozycja czasami ma sens, na przykład wywoływanie new DateTimew php lub new std::vector<int>w C ++. Ale najczęściej jest to ostrzeżenie, że Twój projekt kodu jest nieprawidłowy.
W przypadku, gdy class Abyłby to specjalny obiekt używany do buforowania, class Bzawsze byłby buforowany przy użyciu implementacji class Ai nie miałbyś żadnej kontroli, aby dynamicznie go zmieniać, co jest złe.
Ponadto, jeśli użyjesz leniwej kompozycji inicjalizacyjnej , co oznacza, że będziesz miał działającą metodę object B, zwaną useA()metodą, a tworzenie się object Anie powiedzie, twoja object Bnagle stanie się bezużyteczna.
Z drugiej strony agregacja jest sposobem relacji, który jest zgodny z zasadą DI . object Bmusi użyć object A, to powinieneś przekazać już utworzoną instancję object Ado object B, a jeśli tworzenie się object Anie powiedzie, nic nie zostanie przekazane w pierwszej kolejności.
W skrócie, Agregacja jest reprezentacją UML dla zasady wstrzykiwania zależności , czy to wstrzykiwania do konstruktora, wstrzykiwania setera czy wstrzykiwania własności publicznej.
To są wszystkie agregacje
Najściślejszy wtrysk konstruktora ( object Bnie może istnieć bez object A).
final class B
{
private $a;
public function __construct(A $a)
{
$this->a = $a;
}
}
Looser (możesz lub nie możesz używać w object Aśrodku object B, ale jeśli to zrobisz, prawdopodobnie powinieneś go najpierw ustawić).
Za pomocą setera:
final class B
{
private $a;
public function setA(A $a)
{
$this->a = $a;
}
}
Za pośrednictwem własności publicznej:
final class B
{
public $a;
}
Nie ma naprawdę świetnego sposobu na uzasadnienie użycia Agregacji zamiast Kompozycji, jeśli wszystko, czego używasz, to konkretne implementacje klas, ale kiedy zaczniesz wstrzykiwać interfejsy lub w przypadku klas abstrakcyjnych C ++, nagle Agregacja będzie jedynym sposobem na wypełnij swój kontrakt.