Parancs programtervezési minta

Az objektumorientált programozásban, a parancs minta egy viselkedési forma, amelyben egy objektumot használunk arra, hogy reprezentáljunk és párosítsunk minden olyan információt, amely szükséges lehet egy metódus későbbi meghívásához. Ezen információk közé tartozik a metódus neve, az objektum amely birtokolja a metódust és az értékeit a metódus paramétereinek. Az alábbi négy pont mindig együtt említendő a parancs mintával kapcsolatban, melyek nem mások mint a

  • (Command) parancs,
  • (Receiver) vevő,
  • (Invoker) felhasználó [meghívó],
  • (Client) ügyfél.

A parancs objektumnak van egy vevő objektuma és ennek meghívja egy metódusát. A vevő ezután elvégzi a munkát. A parancs objektum el van különítve egy felhasználó objektumnak, amely meghívja a parancsot. Minden parancs objektum átadható ugyanannak a felhasználó objektumnak. Mind a felhasználó objektum és néhány parancs objektum az ügyfél objektum birtokában van. Az ügyfél tartalmazza a döntéshozatalt, hogy melyik parancsot kell végrehajtani, az adott ponton. Egy parancs végrehajtása azt jelenti, hogy egy parancs objektumot átadunk a felhasználó objektumnak. Lásd a példákat lentebb.

A Parancs objektumok használata könnyebbé teszi az általános komponensek létrehozását, amik szükségesek a „Delegate”, szekvenciális, vagy végrehajtó metódusok meghívásához anélkül, hogy tudnánk a "class"-unk metódusát, vagy annak paramétereit. A felhasználó (Invoker) objektum használata lehetőséget biztosít a naplózásra a parancs végrehajtások könnyű elvégezhetőségének érdekében, amennyiben végrehajtunk különböző parancsokat, amelyek egy felhasználó objektum által vannak vezérelve, anélkül, hogy az ügyfél tudatában lenne naplózásnak, vagy módoknak.

Felhasználása

A parancs objektumok az implementáláshoz hasznosak.

GUI gombok és menü elemek

Swing és Borland Delphi programozási nyelvekben, az „Action” (művelet) egy parancs objektum. Amellett, hogy képes végrehajtani a kívánt parancsot, egy „Action” lehet egy társított ikon, egy billentyűzet gyorsbillentyű, tooltip, és így tovább. Egy eszköztár gomb, vagy egy menüpont összetevője létrejöhet kizárólag egy „Action” vezérlése végett.

Makró felvétel

Ha minden felhasználói „Action” (művelet) egy parancs objektum által van reprezentálva, akkor a program képes rögzíteni egy művelet szekvenciáját egyszerűen azáltal, hogy egy listát tart a parancs objektumokról, ahogy őket meghívták. Ezt követően „újrajátssza” ugyanazt a műveletet azáltal, hogy meghívja a parancs objektumon ugyanabban a szekvenciában. Ha a program "Script" motort is tartalmaz, minden parancs objektum implementálhat egy toScript() metódust, és a felhasználói műveletek akkor könnyebben rögzítve lehetnek "Script"-ként.

Mobil kódolás

Olyan nyelveket használva, mint például Java, ahol a kód "Stream"-elhető egy bizonyos távoli helyről egy másikra "URLClassloader"-ek és "Codebase"-k segítségével, ott a parancsok lehetővé tesznek egy újfajta viselkedéseket, a távoli helyeken. (EJB Command, Master Worker)

A többszintű visszavonás

Ha minden felhasználói művelet egy parancs objektum által van implementálva, akkor a program egy veremben tárolja a legutóbb használt végrehajtott parancsokat. Amikor a felhasználó vissza akar vonni egy parancsot, a program egyszerűen visszaadja a legutóbbi parancs objektumot, és végrehajtja az undo() metódust.

Networking

Lehetőség van rengeteg parancs objektum küldésére a hálózaton keresztül, hogy végrehajtsuk azt egy másik számítógépen.

Párhuzamos feldolgozás

Itt a parancsok „task”-ként, feladatokként vannak megírva egy megosztott erőforrás részére és több szál által vannak végrehajtva párhuzamosan. (Valószínűleg egy távoli számítógépen)

Folyamatjelzők

Feltételezzük, hogy egy program parancsok soraiból épül fel melyek sorban hajtódnak végre. Parancs objektumonként van egy getEstimatedDuration() metódusunk, mellyel, a program könnyen megbecsüli annak teljes hosszát (időtartamát). Ez tükröződhet egy folyamatjelző által, mely észszerűen mutatja, hogy milyen közel van a program ahhoz, hogy végezzen az összes feladattal.

Thread pools (Szálcsoportok)

Egy tipikus, általános célú szálcsoport osztálynak rendelkeznie kell egy publikus addTask() metódussal, amely hozzáad egy munkaeszközt egy belső feladat sorához (queue-hoz) várván a feladat befejezésére. Ez azt jelenti, hogy a szálcsoport meghívja a parancsokat a (queue-ból) sorból. A sor elemei parancs objektumok. Általában ezek az objektumok egy közös interfészt (common interface-t) implementálnak, mint például „java.lang.Runnable” amely lehetőséget nyújt a szálcsoportoknak, hogy végrehajtsák a parancsokat még akkor is, ha maga a szálcsoport osztály úgy van megírva, hogy nincs ismerete a konkrét feladatokról.

Tranzakciós viselkedés

Hasonlóan a visszavonáshoz, egy adatbázis motor, vagy egy szoftver telepítő tartalmazhat egy listát a műveletekről, amely végre lettek, vagy végre lesznek hajtva. Amennyiben valamelyikük nem sikerül, az összes többi visszafordítható vagy eldobható (általában „rollback”-nek hívják). Például, ha van két adatbázis tábla, melyek hivatkoznak egymásra, amiket frissíteni kell, és a második frissítés nem sikerül, a tranzakció visszaállítható, így az első tábla nem tartalmaz majd hibás hivatkozásokat.

Wizards (Varázslók)

Gyakran egy varázsló több oldalnyi konfigurációs lapot mutat be egyetlen művelet érdekében, mely csak akkor következik be, ha a felhasználó rákattint a „Kész” gombra az utolsó oldalon. Ezekben az esetekben a természetes út a felhasználói interfész kódjának és az alkalmazás kódjának szétválasztása érdekében, hogy implementáljuk a varázslót parancs objektum használatával. A parancs objektum akkor jön létre, amikor a varázsló először megjelenik. A varázsló minden oldalában tárolja a GUI változásokat a parancs objektumban, tehát az objektum annyira előrehaladott (belakott), amennyire a felhasználó halad. A „Kész” gomb egyszerűen elindít egy „execute()” hívást. Ezen a ponton kezdődik a parancs osztály munkája, a parancsok sorozatának végrehajtása.