všetky vzory

Visitor

Pridá operáciu nad štruktúrou objektov bez zásahu do ich tried.

class Shape {  accept(visitor) { throw new Error('abstraktná metóda'); }} class Circle extends Shape {  constructor(r) {    super();    this.r = r;  }   // Circle performs no operation. It hands over control and passes itself.  accept(visitor) {    visitor.visitCircle(this);  }} class Square extends Shape {  constructor(a) {    super();    this.a = a;  }   accept(visitor) {    visitor.visitSquare(this);  }} class Visitor {  visitCircle(circle) { throw new Error('abstraktná metóda'); }  visitSquare(square) { throw new Error('abstraktná metóda'); }} class AreaCalculator extends Visitor {  visitCircle(circle) {    return Math.PI * circle.r * circle.r;  }   visitSquare(square) {    return square.a * square.a;  }} const area = new AreaCalculator();circle.accept(area);square.accept(area);

Celý priebeh v texte (8 krokov)
  1. Shape je abstraktný a vie jedinú vec: prijať návštevníka. Circle aj Square ho dedia — a to je všetko, čo o operáciách vedia.
  2. Vpravo je druhá hierarchia: operácie. AreaCalculator je jedna z nich a nesie celý výpočet — ten nie je v žiadnom z tvarov.
  3. Klient povie Circle: prijmi tohto návštevníka.
  4. A tu je vzor: Circle nevypočíta nič. Odrazí volanie späť von — zavolá návštevníka a podá mu seba. Prvé volanie určilo, ktorý tvar; druhé, ktorá operácia. To je dvojité odoslanie.
  5. To isté so Square. Klient volá rovnako a o výpočte nevie nič.
  6. Aj Square len odovzdá riadenie — ale inou metódou, lebo je iný typ. Návštevník tak vie, s čím pracuje, bez toho, aby sa na to musel pýtať.
  7. Celý výpočet plochy je na jednom mieste, v jednej triede — nie rozdrobený po tvaroch. A nová operácia znamená nového návštevníka: tvary sa nezmenia ani o písmeno.
  8. Cena je opačná strana tej istej mince: pridať nový tvar znamená zasiahnuť do každého návštevníka. Vzor uľahčuje pridávanie operácií a sťažuje pridávanie typov — oplatí sa tam, kde je skupina tried ustálená.

Kedy použiť

  • Nad ustálenou skupinou tried pribúdajú operácie — každá je jeden návštevník.
  • Výpočet plochy, export, kontrola — sú to veci o tvaroch, nie vlastnosti tvarov.
  • Celý výpočet je v jednej triede, nie rozdrobený po všetkých prvkoch.
  • Cudzie triedy sa meniť nedajú, ale jedinú metódu prijmi() pustia dnu.

Pasce

  • Pridať typ je drahé, pridať operáciu lacné — nový tvar zasiahne každého návštevníka.
  • Dvojité odoslanie sa ťažko číta: volanie ide do prvku a odtiaľ späť do návštevníka.
  • Prvky musia návštevníkovi vydať svoj stav a zapuzdrenie tým trpí.
  • Metóda prijmi() je v prvkoch kvôli cudzím operáciám; nezávislosť nie je úplná.
  • Zamieňa sa s Iteratorom: ten rieši, ako štruktúru prejsť, návštevník, čo s prvkom urobiť.
  • Návštevník, ktorý si medzi prvkami niečo zbiera, dá pri druhom prechode zlý výsledok.
  • Pri piatich tvaroch má každý návštevník päť takmer rovnakých metód.