všetky vzory

Iterator

Prechádza prvky kolekcie bez toho, aby odhalil jej vnútornú stavbu.

class ZoznamIterator {  constructor(prvky) {    this.prvky = prvky;    this.pozicia = 0;  }   maDalsi() {    return this.pozicia < this.prvky.length;  }   dalsi() {    const prvok = this.prvky[this.pozicia];    this.pozicia += 1;    return prvok;  }} class Zoznam {  #prvky = [];   pridaj(prvok) {    this.#prvky.push(prvok);  }   iterator() {    return new ZoznamIterator(this.#prvky);  }} const it = zoznam.iterator();while (it.maDalsi()) {  spracuj(it.dalsi());   // klient nevie, čo je vnútri zoznamu}

Celý priebeh v texte (11 krokov)
  1. Zoznam drží tri prvky. Ako presne — v poli, v spájanom zozname, v strome — klienta nezaujíma a nikdy sa to nedozvie.
  2. Iterátor je jediné, čo o vnútri zoznamu vie. Klient drží jeho a nič iné — kolekciu nevolá ani raz.
  3. Klient povie iterátoru: daj ďalší.
  4. Iterátor sa nastaví na prvý prvok. Prvok zostáva v zozname — von ide len to, kde iterátor práve stojí.
  5. Druhé volanie. To isté ako predtým, klient nič nepočíta a nič si nepamätá.
  6. A kurzor sa posunie. Pozíciu si drží iterátor, nie kolekcia a nie klient — preto môžu nad tým istým zoznamom bežať aj dva prechody naraz.
  7. Tretie volanie.
  8. Kurzor na treťom prvku.
  9. Štvrté volanie — klient sa pýta, či je ešte niečo.
  10. Za tretím prvkom už nič nie je. Kurzor sa nikam neposunie a iterátor povie, že prechod skončil.
  11. Klient prešiel celú kolekciu a ani raz sa nedotkol jej vnútra — všetky tri prvky sú stále tam, kde boli. Vymeňte zoznam za strom a klientov kód sa nezmení ani o písmeno.

Kedy použiť

  • Kolekciu treba prejsť bez toho, aby volajúci vedel, ako je uložená. Pole, spájaný zoznam či strom sa prechádzajú tým istým kódom.
  • Vnútro kolekcie má zostať skryté. Bez iterátora by ho musela vydať von — a potom už nemá zmysel ho skrývať.
  • Nad tou istou kolekciou má bežať viac prechodov naraz. Každý iterátor si drží vlastnú pozíciu, takže sa navzájom nerušia.
  • Prechodov je viac druhov. Dopredu, dozadu, po listoch, po úrovniach — každý je vlastný iterátor a kolekcia zostáva nezmenená.
  • Prvky sa majú vydávať postupne, nie naraz. Pri veľkej alebo nekonečnej postupnosti je jediná možnosť brať ich po jednom.

Pasce

  • Zmena kolekcie počas prechodu rozbije pozíciu. Iterátor si drží index alebo odkaz do vnútra a nikto ho neupozorní, že sa to vnútro medzitým zmenilo.
  • Pozícia je stav, ktorý sa dá použiť len raz. Prejdený iterátor sa nedá spustiť znova — kto to skúsi, dostane prázdno bez chyby.
  • Iterátor pozná vnútro kolekcie a je s ňou zviazaný. Zmena uloženia znamená prepísať aj ho; navonok sa nezmení nič, no dvojica musí sedieť.
  • Prechod po jednom je pomalší než hromadná operácia. Pri každom prvku sa volá metóda a to je pri veľkých kolekciách cítiť.
  • Zamieňa sa s Composite. Kompozit prechádza strom sám, zvnútra, a klient len zavolá koreň. Iterátor prechod riadi zvonku a jeho tempo určuje volajúci.
  • Skrytá zložitosť. Prechod, ktorý vyzerá rovnako pre pole aj pre spájaný zoznam, môže mať zakaždým celkom inú cenu.