Kolekce a asociace (1:N, M:N)
Proč to potřebuji?
Většina reálných vztahů mezi objekty má kardinalitu vyšší než 1:1. Kolekce jsou nezbytným nástrojem pro implementaci vztahů 1:N a M:N, které najdete prakticky v každé aplikaci.
Teorie
Vztah 1:N se implementuje tak, že strana „1" drží kolekci (typicky List) odkazů na stranu „N". Vztah M:N vyžaduje kolekci na obou stranách, nebo pomocnou třídu (vazební entita).
Agregace: objekt je přidáván zvenčí (předán jako parametr). Kompozice: objekt je vytvářen uvnitř vlastníka.
Příklady
// === 1:N – Kurz má mnoho studentů ===
public class Kurz {
private String nazev;
private List<Student> studenti = new ArrayList<>();
public Kurz(String nazev) {
this.nazev = nazev;
}
public void zapisStudenta(Student s) {
if (!studenti.contains(s)) {
studenti.add(s);
}
}
public void odhlasStudenta(Student s) {
studenti.remove(s);
}
public List<Student> getStudenti() {
return Collections.unmodifiableList(studenti); // ochrana
}
}
// === M:N – Student může mít více kurzů, kurz více studentů ===
public class Student {
private String jmeno;
private List<Kurz> kurzy = new ArrayList<>();
public Student(String jmeno) {
this.jmeno = jmeno;
}
public void zapisDoKurzu(Kurz k) {
if (!kurzy.contains(k)) {
kurzy.add(k);
k.zapisStudenta(this); // obousměrná vazba
}
}
}
// === Kompozice – Objednávka vlastní své položky ===
public class Objednavka {
private List<Polozka> polozky = new ArrayList<>();
// Položka se VYTVÁŘÍ uvnitř – kompozice
public void pridejPolozku(String nazev, int pocet) {
polozky.add(new Polozka(nazev, pocet));
}
// Vnitřní třída – zdůrazňuje vlastnictví
private static class Polozka {
String nazev;
int pocet;
Polozka(String nazev, int pocet) {
this.nazev = nazev;
this.pocet = pocet;
}
}
}
Shrnutí
Klíčové body
- 1:N →
List<T>na straně „1" - M:N → kolekce na obou stranách + synchronizace obou směrů
- Agregace = objekt přijat zvenčí, Kompozice = vytvořen uvnitř
Collections.unmodifiableList()chrání interní kolekci