všetky vzory

Interpreter

Vyjadrí gramatiku jazyka objektmi a vyhodnotí zapísané výrazy.

class Vyraz {  vyhodnot() { throw new Error('abstraktná metóda'); }} class Cislo extends Vyraz {  constructor(hodnota) {    super();    this.hodnota = hodnota;  }   vyhodnot() {    return this.hodnota;  }} class Zapor extends Vyraz {  constructor(operand) {    super();    this.operand = operand;  }   vyhodnot() {    return -this.operand.vyhodnot();  }} class Sucet extends Vyraz {  constructor(lavy, pravy) {    super();    this.lavy = lavy;    this.pravy = pravy;  }   vyhodnot() {    return this.lavy.vyhodnot() + this.pravy.vyhodnot();  }} // Zapísaný výraz 5 + (-3) je strom objektov, nie text.const vyraz = new Sucet(new Cislo(5), new Zapor(new Cislo(3))); vyraz.vyhodnot();   // 2

Celý priebeh v texte (12 krokov)
  1. Vyraz je abstraktný a vie jediné: vyhodnotiť sa. Každé pravidlo gramatiky je trieda, ktorá ho dedí — čísla aj operácie.
  2. Zapísaný výraz 5 + (-3) nie je text, ale strom objektov. Súčet drží dva operandy: číslo a ďalšiu operáciu.
  3. Klient vyhodnotí koreň stromu. Jedno volanie na jednom objekte.
  4. Súčet sa nepýta, čo v ňom je — zavolá vyhodnotenie na prvom operande.
  5. Cislo je terminál. Nemá čo počítať a nemá koho volať — jednoducho vráti svoju hodnotu. A tu sa začína to podstatné: hodnota putuje hore.
  6. Teraz druhý operand.
  7. Lenže Zapor nie je číslo, je to operácia — takže sa pýta ďalej. Volanie ide o poschodie nižšie a to je rekurzia.
  8. Aj tu je na konci terminál a aj tu sa hodnota vracia hore.
  9. Zapor z nej spraví svoju — otočí znamienko — a pošle ju o poschodie vyššie. Pôvodnú si nechá, tá bola vstupom.
  10. Súčet má teraz obe hodnoty vedľa seba a vie z nich vypočítať svoju.
  11. Výsledok putuje klientovi. Ten dostal jedno číslo a o strome, ktorým prešlo volanie, nevie nič.
  12. Gramatika je hierarchia tried, zapísaný výraz je strom ich instancií a vyhodnotenie je rekurzia po ňom. Volanie zostupovalo, hodnoty stúpali — a v každom uzle z nich vznikla nová.

Kedy použiť

  • Gramatika je malá a stabilná. Filtre, pravidlá, jednoduché podmienky — každé pravidlo sa dá zapísať ako jedna trieda a celé to zostane prehľadné.
  • Ten istý výraz treba vyhodnotiť mnohokrát. Rozobrať ho raz na strom objektov je lacnejšie než ho pri každom použití čítať znova z textu.
  • Nad výrazom treba robiť viac než len vyhodnotenie. Strom objektov sa dá aj vypísať, zjednodušiť alebo skontrolovať — text sa nedá nič z toho.
  • Používateľ má vedieť zapísať pravidlo bez zásahu do programu. Jazyk je vtedy súčasťou rozhrania a jeho gramatika musí niekde existovať ako kód.

Pasce

  • Rastie so zložitosťou gramatiky, a to rýchlo. Každé pravidlo je trieda, takže pri skutočnom jazyku ich budú desiatky — vtedy treba parser a nie tento vzor.
  • Vzor rieši vyhodnotenie, nie čítanie. Ako sa z textu stane strom objektov, nehovorí ani slovo — to je práca, ktorú treba spraviť inde a býva väčšia než samotné vyhodnotenie.
  • Zamieňa sa s Composite. Štruktúra je naozaj tá istá — strom objektov s jedným rozhraním — ale kompozit skladá celok z častí, kým interpreter vyhodnocuje zápis v jazyku. Prvý má strom ako dáta, druhý ako program.
  • Každá nová operácia znamená zásah do všetkých tried. Pridať k vyhodnoteniu ešte výpis znamená doplniť metódu do každého pravidla — a to je presne prípad pre Visitora.
  • Rekurzia po hlbokom strome dosiahne dno zásobníka. Výraz zapísaný používateľom môže byť ľubovoľne vnorený a program to nemá ako čakať.
  • Kontext sa vlečie cez celý strom. Premenné a nastavenie musí dostať každé pravidlo, aj tie, ktoré ich nikdy nepoužijú.