September discount week
Pouze tento týden sleva až 80 % na e-learning týkající se MS Office
50 % bodů zdarma na online výuku díky naší Slevové akci!

Lekce 16 - Memento

V minulé lekci, State, jsme si ukázali návrhový vzor State, který umožňuje objektu razantně změnit své chování, které je závislé na stavu tohoto objektu. Nyní víme, že nahrazuje složité větvení uvnitř objektu.

Memento (památka) je jednoduchý návrhový vzor chování, který řeší uložení vnitřního stavu objektu, aniž by byl porušen princip zapouzdření. Jelikož vnitřní stav je uvnitř objektu zapouzdřen, musí uložení dat objektu provést objekt sám. K vnitřnímu stavu se lze poté vrátit. V základní verzi tohoto vzoru se nejedná o princip historie (zpět a vpřed), ale opravdu o jeden stav, který se uloží a objekt se do něj poté dokáže vrátit. Princip historie lze nicméně doimplementovat a to i inkrementálně, aby se ukládaly pouze změny oproti původním datům. Vzor nijak neřeší jak ukládání stavu implementovat, pro tyto účely můžeme použít např. serializaci.

Motivace

V našich aplikacích můžeme na některých místech vyžadovat možnost vrátit se k předchozímu stavu, např. získat data z formuláře, který uživatel vyplnil a po jehož odeslání došlo k výpadku internetového připojení. Můžeme také potřebovat zavést funkce zpět/vpřed, ty se hodí ať programujeme kalkulačku nebo např. nějaký editor. Asi vás nepřekvapí, že vzor bude oddělovat tuto funkcionalitu do samostatného objektu. To je konec konců princip, o který se většina vzorů snaží. Původní třída uchovávající stav tak zůstane nezanesená touto logikou a bude lépe udržovatelná.

Vzor

Vzor obsahuje následující třídy:

  • Originator - Třída, jejíž stav ukládáme. Umožňuje svůj stav načíst z mementa nebo jej uložit do nového mementa a vrátit.
  • Memento - Reprezentace vnitřního stavu třídy Originator. Pouze objekt držící stav bez další logiky.
  • Caretaker - Třída ukládá/načítá mementa z/do originatoru, jedná se o manažer stavů.
Návrhový vzor Memento z GOF

Příklad

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Představme si, že chceme uchovávat historii výpočtů kalkulačky. Pro zjednodušení ukládejme pouze celé zadané příklady jako textové řetězce. Pro reprezentaci historie využijeme datovou strukturu zásobník. V praxi samozřejmě můžete ukládat objekty s libovolným počtem libovolně složitých vlastností. Memento můžeme naprogramovat i generický, abychom jej mohli využívat i pro další třídy a nemuseli psát zbytečně nové třídy.

Třída Memento:

public class Memento<T>
{

    private T data;

    public Memento(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }

}

Třída Originator (Kalkulačka):

public class Kalkulacka<T> {
    private T priklad;

    public Memento<T> uloz() {
        return new Memento(priklad);
    }

    public void nacti(Memento<T> memento) {
        priklad = memento.getData();
    }

    public void setPriklad(T priklad) {
        this.priklad = priklad;
    }

    public T getPriklad() {
        return priklad;
    }

    // Nějaké další metody kalkulačky...

}

A třída Caretaker:

public class Caretaker<T> {
    private Kalkulacka<T> kalkulacka;
    private Stack<Memento<T>> historie = new Stack<Memento<T>>();

    public Caretaker(Kalkulacka kalkulacka) {
        this.kalkulacka = kalkulacka;
    }

    public void uloz() {
        historie.push(kalkulacka.uloz());
    }

    public void zpet() {
        kalkulacka.nacti(historie.pop());
    }

}

Použití je následující:

Kalkulacka kalkulacka = new Kalkulacka();
Caretaker<String> historie = new Caretaker<>(kalkulacka);
kalkulacka.setPriklad("1 + 1");
System.out.println(kalkulacka.getPriklad());
historie.uloz();
kalkulacka.setPriklad("2 * 3");
System.out.println(kalkulacka.getPriklad());
historie.zpet();
System.out.println(kalkulacka.getPriklad());

A výstup aplikace:

Konzolová aplikace
1 + 1
2 * 3
1 + 1

Pokud by vás zajímalo, jak naprogramovat výpočet takového matematického výrazu, řeší to návrhový vzor Interpreter, také z GOF.

V další lekci, Interpreter, si ukážeme návrhový vzor chování Interpreter, který definuje, jakým způsobem implementovat interpretaci nějakého jazyka pomocí objektově orientovaného programování.


 

Předchozí článek
State
Všechny články v sekci
Návrhové vzory GoF
Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
1 hlasů
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn university Autor sítě se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity (3)

 

 

Komentáře

Avatar
Matej Končal:26. dubna 23:43

Podla mojho nazoru je priklad trochu zavadzajuci, pretoze memento je tu implementovane tak, ze bude fungovat len s prim. dat. typomi. V opacnom pripade sa do premennej data ulozi len referencia.

 
Odpovědět
26. dubna 23:43
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 1 zpráv z 1.