všetky vzory

Strategy

Vloží zameniteľný algoritmus do objektu, ktorý sa dá podsunúť za behu.

class Trasa {  najdi(odkial, kam) { throw new Error('abstraktná metóda'); }} class Autom extends Trasa {  najdi(odkial, kam) {    // po cestách, najkratší čas  }} class Pesi extends Trasa {  najdi(odkial, kam) {    // aj cez parky a schody  }} class Navigacia {  #trasa;   // Stratégiu podáva klient. Navigácia si ju sama nikdy nevymení.  nastavTrasu(trasa) {    this.#trasa = trasa;  }   najdi(odkial, kam) {    return this.#trasa.najdi(odkial, kam);  }} const navigacia = new Navigacia(); navigacia.nastavTrasu(new Autom());navigacia.najdi(domov, praca); navigacia.nastavTrasu(new Pesi());navigacia.najdi(domov, praca);

Celý priebeh v texte (10 krokov)
  1. Trasa je abstraktná a dva algoritmy ju dedia. Navigácia pozná len ju — o aute ani chodcovi nevie nič.
  2. Klient povie navigácii, ako má hľadať. Toto volanie je celý rozdiel oproti vzoru State: stratégiu podáva on.
  3. Navigácia si ju odloží. Sama by si ju nikdy nevybrala — nemá podľa čoho.
  4. Klient si vypýta trasu.
  5. Navigácia sa nerozhoduje — pošle dopyt tomu, koho práve drží.
  6. Teraz sa klient rozhodne inak a podá druhú stratégiu. Všimni si, že výmenu opäť spustil on — navigácia ju sama neurobila a ani nemá ako.
  7. Odkaz v komore sa vymenil. Autom a Pesi o sebe navzájom nevedia — nie sú prepojené, sú to len dva nezávislé algoritmy.
  8. Ten istý dopyt ako pred chvíľou.
  9. Ten istý kód navigácie, iný algoritmus. Trasa vyjde celkom inak, hoci sa v navigácii nezmenilo nič.
  10. Navigácia sa nezmenila a stratégiu si nikdy nevymenila sama — každú výmenu priniesol klient. Keby sa vymieňala sama ako dôsledok volania a algoritmy o sebe vedeli, bol by to State.

Kedy použiť

  • Tú istú úlohu treba riešiť viacerými spôsobmi a voľba padá až za behu. Algoritmus sa podá zvonku a volajúci kód zostáva rovnaký.
  • Podmienka vyberá medzi variantmi toho istého výpočtu. Každá vetva sa stane triedou a rozhodovanie zmizne z miesta, kde sa počíta.
  • Algoritmus treba vedieť otestovať samostatne. Ako objekt sa dá spustiť bez kontextu, ktorý ho inak používa.
  • Variantov bude pribúdať. Nový spôsob znamená novú triedu a nič iné — do existujúceho kódu sa nesiaha.
  • Detaily výpočtu nemá volajúci poznať. Vidí len rozhranie a to, čo je za ním, ho nemusí zaujímať.

Pasce

  • Zamieňa sa so State. Štruktúra je tá istá — kontext drží odkaz na abstrakciu — ale rozhoduje, kto ten odkaz mení. Stratégiu podáva klient a kontext si ju sám nikdy nevymení; stav sa vymieňa sám ako dôsledok volania. Stratégie o sebe navzájom nevedia, stavy áno.
  • Klient musí stratégie poznať. Aby si mohol vybrať, musí vedieť, čo ktorá robí — vzor skryje algoritmus pred kontextom, nie pred tým, kto ho volí.
  • Rozhranie sa nafúkne podľa najnáročnejšieho variantu. Keď jedna stratégia potrebuje viac vstupov než ostatné, dostanú ich všetky a väčšina ich nepoužije.
  • Pri dvoch krátkych variantoch je podmienka lacnejšia. Trieda a rozhranie navyše sa oplatia až vtedy, keď variantov pribúda alebo sú dlhé.
  • Stratégia so stavom prestane byť zameniteľná. Keď si medzi volaniami niečo pamätá, nedá sa zdieľať a podsunúť inú znamená stratiť to, čo si pamätala.
  • Zamieňa sa s Command. Príkaz hovorí, čo sa má stať, a dá sa odložiť či vrátiť; stratégia hovorí, ako sa niečo urobí, a vykoná sa hneď.