všetky vzory

Composite

Umožní pracovať so stromom objektov rovnako ako s jediným objektom.

class Item {  size() { throw new Error('abstraktná metóda'); }} class File extends Item {  constructor(bytes) {    super();    this.bytes = bytes;  }   size() {    return this.bytes;  }} class Folder extends Item {  children = [];   add(item) {    this.children.push(item);  }   size() {    let total = 0;    for (const child of this.children) {      total += child.size();    }    return total;  }} const album = new Folder();album.add(new File(900)); const root = new Folder();root.add(new File(120));root.add(album); root.size();   // 1020 — the client never asked what is inside

Celý priebeh v texte (11 krokov)
  1. Item je abstraktný a vie jediné: povedať svoju veľkosť. Dedia ho obe strany stromu — súbor aj priečinok. Práve preto sa dá so stromom pracovať ako s jedným objektom.
  2. Root je priečinok, takže drží deti — dve. Jedno je súbor, druhé je zase priečinok, a je to možné práve preto, že oba sú Item.
  3. A Album drží svoje vlastné dieťa. Strom je tým postavený a má tri poschodia — lanká sú väzby rodič a dieťa.
  4. Klient zavolá size() na koreni. Je to jedno volanie na jednom objekte — o tom, čo je vnútri, nevie a ani nechce vedieť.
  5. Root sa nepýta, čo v ňom je. Pošle to isté volanie prvému dieťaťu.
  6. a.txt je list. Nemá deti, takže volanie nikam ďalej neposiela — jednoducho odpovie.
  7. Druhé dieťa dostane presne to isté volanie. Root nerobí rozdiel medzi prvým a druhým, oba sú preň len Item.
  8. Lenže Album je priečinok — a spraví presne to, čo pred chvíľou koreň: pošle to isté volanie ďalej svojmu dieťaťu. Toto je rekurzia a je to celý vzor.
  9. b.jpg je zase list, takže tu sa vetvenie končí.
  10. Album spočíta odpovede svojich detí a vráti výsledok koreňu, ako keby bol obyčajný súbor. Koreň spočíta to svoje a vráti klientovi jedno číslo.
  11. Jedno volanie na jednom objekte prešlo celý strom. A v žiadnom kroku sa nikto nespýtal „si list alebo priečinok?" — to je presne tá otázka, ktorú vzor odstraňuje.

Kedy použiť

  • Priečinok aj súbor odpovedia na tú istú otázku a volajúci nemusí vedieť, ktorý z nich drží.
  • Otázka „je to jeden alebo skupina?" zmizne — skupina je tiež jeden.
  • Hĺbka stromu nie je známa dopredu a rekurzia ju zvládne bez jediného cyklu u klienta.
  • Ten istý kód spracuje celý strom aj jediný list.

Pasce

  • Jednotné rozhranie dá listu pridaj() a odober(); bezpečné vráti klientovi otázku na typ.
  • Nič nebráni tomu, aby sa priečinok stal svojím potomkom, a prechod stromom potom neskončí.
  • Jedno volanie vyzerá ako jedno volanie, no môže prejsť státisíce uzlov.
  • Zamieňa sa s Decoratorom: ten obaľuje jeden objekt a pridáva chovanie, kompozit ich drží viac.
  • Kým operácia len sčítava, na poradí detí nezáleží; pri prvej, ktorej záleží, ho nikto nezaručil.
  • Spätný odkaz na rodiča vyrobí cyklus vo vlastníctve a upratovanie stromu prestane byť triviálne.