Warning
This page is located in archive. Go to the latest version of this course pages. Go the latest version of this page.

Možné řešení z minulého cvičení

Teorie

Vzor Interpreter

Problém

Pro určitý (formální) jazyk chceme vytvořit reprezentaci pomocí objektů v paměti, abychom mohli pracovat s výrazy v tomto jazyce a vyhodnocovat je.

Řešení

Vzor interpreter popisuje jak definovat gramatiku pro jednoduchý jazyk, reprezentovat výrazy v tomto jazyce a interpretovat je.

Hierarchická reprezentace výrazu obsahuje dva základní druhy prvků:

  • primitivní výraz, který je kompletní sám o sobě a ke svému vyhodnocení nepotřebuje žádné další výrazy
  • složený výraz, který se skládá z libovolných dalších výrazů (primitivních či složených) a tyto výrazy potřebuje ke svému vyhodnocení

Podobná hierarchie je reprezentována návrhovým vzorem Composite, který má obecnější použití než jen pro reprezentaci výrazů.

Vzor Visitor

Problém

Chceme vytvořit operaci pracující s elementy objektové struktury. Může se jednat o mnoho samostatných a nesouvisejících operací. Chceme však zabránit znepřehlednění kódu objektů těmito operacemi a chceme mít možnost definovat nové operace beze změny tříd se kterými pracují.

Řešení

Vzor visitor primárně abstrahuje funkcionalitu, která může být aplikována na celou hierarchii objektů.

Triviálním řešením by bylo vytvoření třídy, do které umístíme samostatnou metodu pro každou podtřídu hierarchie objektů. Veřejná bude pouze metoda přijímající kořenovou třídu hierarchie a dále se pomocí if podmínek a ověření typu parametru rozhodne, kterou z následujících metod zavolá.

Efektivnější řešení využívá takzvaný double dispatch. Java však podporuje pouze single dispatch, při kterém je volání metody závislé na názvu metody a identifikaci příjemce. Návrhový vzor visitor toto rozšiřuje o identifikaci odesílatele. První směrování požadavku je od objektu Visitor ke konkrétnímu elementu, který odpovědí zpět objektu Visitor souhlasí s návštěvou a identifikuje typ třídy.

Příklady k řešení

Stáhněte si z repository základ cvičení 8:

https://gitlab.fel.cvut.cz/B231_B6B36OMO/seminar/-/tree/master/cv8_assignment

Přečtěte si o Immutable Collections

Implementace ve cvičení 8 bude v následujících krocích

1. Do připraveného programu doimplementujte výrazy (operátory), použijte vzor interpreter:

  • IntList: konstantní seznam,
  • VarList: proměnná, jméno proměnné identifikuje seznam definovaný v kontextu pro vyhodnocení výrazu,
  • Remove: odstraní všechny výskyty elementu v podvýrazu, př.: R([1, 2, 3, 2], 2) → [1, 3], zachovává původní pořadí,
  • Concatenate: spojí dva seznamy, př.:C([1,2,3,4],[5,6,7]) → [1,2,3,4,5,6,7],
  • Unique: pro každý prvek vrátí jen jeho první výskyt, př.: U ([3, 2, 1, 2, 2, 1]) → [3, 2, 1], zachovává pořadí,

  • Vysledkem vyhodnocení bude: ImmutableList<Integer>.

2. Přidejte podporu pro vzor visitor a naimplementujte třídu PrintListExpressionVisitor.

  • Použijte prefixovou notaci. Pro názvy neterminalních operátorů stačí první písmeno jejich názvu.
  • Pozor na závorky. Př.: spojení seznamu x a [1,2,3] vytisknete jako C (x, [1, 2, 3]).

3. Naimplementujte visitor (SimplifyListExpressionVisitor), který bude schopen symbolicky zjednodušit výrazy podle následujícího pravidla:

  • Pokud jsou všichni potomci konstantními seznamy, nahradí rodičovský uzel konstantním seznamem s výsledkem vyhodnocení.

Operátor instanceof je přípustný. Nemodifikujte původní vyraz.

Minimalizujte opakování kódu.

Užitečné tipy:

Převod ImmutableList → ArrayList:

List<Integer> list = new ArrayList<>(immutableList);
Převod List → ImmutableList:
ImmutableList<Integer> immutableList = ImmutableList.copyOf(list);
Odstranění všech výskytů prvků element ze seznamu:
list.removeAll(Collections.singleton(element));
Seznamy typu List<Integer> můžete tisknout přímo pomocí System.out.print().

courses/b6b36omo/labs/lab082017.txt · Last modified: 2023/11/14 21:39 by sebekji1