všetky vzory

RAII

Naviaže zdroj na životnosť objektu — pri jeho zániku sa zdroj uvoľní sám.

class FileGuard {  constructor(path) {    // Acquiring the resource is part of creating the object.    this.file = File.open(path);  }   // Destroying the object releases it. Not a step of the program, a consequence.  [Symbol.dispose]() {    this.file.close();  }} function process(path) {  using guard = new FileGuard(path);   write(guard.file);  checkPermissions();   // an error can fly out from here   // End of block. There is no close() anywhere — and the file is closed anyway.}

Celý priebeh v texte (12 krokov)
  1. FileGuard nerobí nič iné, než že drží zdroj. Získa ho pri svojom vzniku a pustí pri svojom zániku — medzi tým nemá žiadnu úlohu.
  2. Funkcia si stráž vytvorí ako lokálnu premennú. Nikto jej ju nepodal a nikam neputuje — vzniká priamo v bloku a jeho život bude aj jej životom.
  3. Vznik stráže je zároveň otvorenie súboru. Konštruktor to spraví sám — nie je to samostatný krok, na ktorý sa dá zabudnúť.
  4. Súbor je otvorený a od tejto chvíle ho stráž drží. Kto má stráž, má zdroj.
  5. Funkcia si robí svoju prácu. O zatváraní v nej nie je ani zmienka.
  6. Blok sa končí. Lokálna premenná zaniká a jej zánik volá close().
  7. A tu je vzor celý: zanikla stráž a s ňou v tom istom okamihu zdroj. V kóde funkcie nie je ani jedno close() — uvoľnenie nie je krok, ktorý by niekto napísal.
  8. Druhý priebeh. Začiatok je rovnaký — stráž vzniká a súbor sa otvára.
  9. Lenže uprostred práce vyletí chyba. Blok sa opúšťa hneď a ani jeden riadok za tým miestom sa nevykoná — keby tam zatvor() bolo napísané, práve teraz by sa preskočilo.
  10. Stráž ale zaniká aj tak. Opustenie bloku je opustenie bloku, či už riadnym koncom alebo chybou.
  11. Súbor je zavretý rovnako spoľahlivo ako pri prvom priebehu.
  12. Dva priebehy, jeden koniec: uvoľnenie zdroja nie je krok programu, ale dôsledok zániku toho, kto ho vlastnil. Práve preto sa nedá zabudnúť, obísť ani preskočiť chybou.

Kedy použiť

  • Zdroj sa uvoľní vždy, aj keď z bloku vyletí chyba — nie je to riadok, čo sa dá preskočiť.
  • Vlastníctvo je čitateľné z typu: kto drží stráž, drží zdroj.
  • Zdrojov je v bloku viac a uvoľnia sa v opačnom poradí samy, bez zásahu programátora.
  • Otvor a zavri, zamkni a odomkni — druhá polovica páru patrí do zániku, nie do disciplíny.

Pasce

  • Tam, kde objekty upratuje garbage collector, sa zdroj uvoľní neskôr alebo nikdy.
  • Uložená alebo vrátená stráž prežije blok a zdroj sa neuvoľní tam, kde sa to čaká.
  • Skopírovaná stráž uvoľní zdroj dvakrát a druhé zatvorenie je chyba.
  • Chyba pri uvoľňovaní nemá kam ísť: zánik beží často vtedy, keď sa už rieši iná chyba.
  • Stráž s vlastnou logikou prestane byť čitateľná — jej úloha je pár získaj a uvoľni.
  • Predčasný koniec bloku zavrie aj spojenie, ktoré malo zostať otvorené.
  • Object Pool objekt požičia a berie späť, stráž ho vlastní a pri zániku ruší.