všetky vzory

Interpreter

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

class Expression {  evaluate() { throw new Error('abstraktná metóda'); }} class NumberLiteral extends Expression {  constructor(value) {    super();    this.value = value;  }   evaluate() {    return this.value;  }} class Negation extends Expression {  constructor(operand) {    super();    this.operand = operand;  }   evaluate() {    return -this.operand.evaluate();  }} class Sum extends Expression {  constructor(left, right) {    super();    this.left = left;    this.right = right;  }   evaluate() {    return this.left.evaluate() + this.right.evaluate();  }} // The written expression 5 + (-3) is a tree of objects, not text.const expression = new Sum(new NumberLiteral(5), new Negation(new NumberLiteral(3))); expression.evaluate();   // 2

Celý priebeh v texte (12 krokov)
  1. Expression 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. NumberLiteral 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 Negation 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. Negation 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.
  • Rozobrať výraz raz na strom je lacnejšie než čítať ho z textu pri každom vyhodnotení.
  • Strom sa dá vypísať, zjednodušiť aj skontrolovať; s textom sa nedá nič z toho.
  • Pravidlo má ísť zapísať bez zásahu do programu — jazyk je vtedy súčasťou rozhrania.

Pasce

  • Každé pravidlo je trieda, takže pri skutočnom jazyku ich budú desiatky — vtedy treba parser.
  • Vzor rieši vyhodnotenie, nie čítanie textu — to je práca inde a býva väčšia.
  • Zamieňa sa s Composite: kompozit skladá celok z častí, interpreter vyhodnocuje zápis v jazyku.
  • Nová operácia znamená doplniť metódu do každého pravidla — prípad pre Visitora.
  • Výraz zapísaný používateľom môže byť vnorený tak hlboko, že rekurzia dosiahne dno zásobníka.
  • Kontext s premennými musí dostať každé pravidlo, aj to, ktoré ho nikdy nepoužije.