Wzorzec projektowy Kompozyt pozwala na tworzenie złożonych struktur drzewiastych z obiektów i traktowanie ich jako pojedynczych jednostek. Jest to szczególnie przydatne w przypadkach, gdy mamy zarówno obiekty prostsze (liście), jak i bardziej złożone (kontenery), które muszą być zarządzane jednolicie.

Wprowadzenie do Wzorca Kompozyt
W codziennym programowaniu często natrafiamy na sytuacje, w których obiekty mają hierarchiczną strukturę elementów. Typowe przykłady to struktury plików i folderów w systemach operacyjnych, hierarchie organizacyjne w przedsiębiorstwach czy też składniki w dynamicznych interfejsach użytkownika. W każdym z tych przypadków potrzebujemy mechanizmu umożliwiającego traktowanie zarówno prostych obiektów, jak i złożonych kontenerów w jednolity sposób.

Kluczowe Koncepcje
- Kompozyt (Composite) – Obiekt, który może zawierać inne obiekty, zarówno kompozyty, jak i liście.
- Liść (Leaf) – Prosty obiekt, który nie zawiera innych obiektów.
- Składnik (Component) – Wspólny interfejs dla kompozytów i liści, definiujący operacje, które mogą być wykonywane na obu typach obiektów.

Implementacja Wzorca Kompozyt
Rozważmy prosty przykład struktury plików, w której zarówno foldery, jak i pliki są traktowane jednolicie.
Składnik – Interface PlikowyElement
interface PlikowyElement {
void pokazZawartosc();
}
Liść – Klasa Plik
class Plik implements PlikowyElement {
private String nazwa;public Plik(String nazwa) {
this.nazwa = nazwa;
}@Override
public void pokazZawartosc() {
System.out.println("Plik: " + nazwa);
}
}
Kompozyt – Klasa Folder
import java.util.ArrayList;
import java.util.List;class Folder implements PlikowyElement {
private String nazwa;
private List<PlikowyElement> zawartosc = new ArrayList<>();public Folder(String nazwa) {
this.nazwa = nazwa;
}public void dodajElement(PlikowyElement element) {
zawartosc.add(element);
}public void usunElement(PlikowyElement element) {
zawartosc.remove(element);
}@Override
public void pokazZawartosc() {
System.out.println("Folder: " + nazwa);
for (PlikowyElement element : zawartosc) {
element.pokazZawartosc();
}
}
}
Użycie Wzorca Kompozyt
Poniższy fragment kodu demonstruje, jak można użyć wzorca Kompozyt do zarządzania hierarchią plików i folderów:
public class Main {
public static void main(String[] args) {
PlikowyElement plik1 = new Plik("Plik1.txt");
PlikowyElement plik2 = new Plik("Plik2.txt");Folder folder1 = new Folder("Folder1");
folder1.dodajElement(plik1);Folder folder2 = new Folder("Folder2");
folder2.dodajElement(folder1);
folder2.dodajElement(plik2);folder2.pokazZawartosc();
}
}
Wynik działania kodu:
Folder: Folder2
Folder: Folder1
Plik: Plik1.txt
Plik: Plik2.txt

Zastosowanie i Korzyści
Wzorzec Kompozyt umożliwia równe traktowanie obiektów prostych i złożonych oraz ułatwia zarządzanie hierarchiami obiektów. Oferuje standaryzowany sposób na implementację operacji, które mogą być wykonywane jednolicie zarówno na pojedynczych elementach, jak i na całych podstrukturalnych hierarchiach.
Główne zalety:
- Prostota: Umożliwia jednolite traktowanie obiektów prostych i złożonych. Wzorzec ten pozwala unikać złożonych instrukcji warunkowych w kodzie klienta.
- Elastyczność: Umożliwia łatwe rozszerzanie drzewiastej struktury przez dodanie nowych typów elementów bez konieczności modyfikowania istniejącego kodu.

Podsumowanie
Wzorzec Kompozyt to jeden z podstawowych wzorców strukturalnych, który doskonale sprawdza się w sytuacjach wymagających reprezentacji złożonych hierarchii obiektów. Dzięki jego zastosowaniu, kod staje się bardziej przejrzysty, elastyczny i łatwiejszy do zarządzania. Jeśli twoja aplikacja wymaga zarządzania złożonymi strukturami danych, Kompozyt może być dla ciebie idealnym rozwiązaniem.