Návrhové vzory Java (design patterns): Chain of Reponsibility

Dnes sa pozrieme na prvý návrhový vzor Chain of Responsibility (java design patterns) z kategórie vzorov správania (behavioral patterns). Návrhové vzory v tejto kategórii sa zaoberajú komunikáciou (interaction) medzi objektami a ich zodpovednosťou (responsibility).

Návrhové vzory Java (design patterns): Chain of Reponsibility
Návrhové vzory Java (design patterns): Chain of Reponsibility

V článku sa dozvieš:

    Čo je návrhový vzor Chain of Responsibility?

    Návrhový vzor Chain of Responsibility (reťaz zodpovednosti) je vzor, ktorý umožňuje viacerým objektom spracovávať požiadavky bez nutnosti, aby objekt vedel, kto je jeho nasledovník v reťazi. Každý objekt v reťazi má možnosť spracovať požiadavku, ale ak nevie, ako ju spracovať, prenáša ju na nasledujúci objekt v reťazi.

    Aký problém návrhový vzor Chain of Responsibility rieši?

    Rieši problém spracovania požiadaviek v reťazi a to tak, že namiesto toho, aby bola požiadavka poslaná na konkrétny objekt, žiadosť putuje reťazou objektov, kde každý objekt v reťazi môže byť zodpovedný za jej spracovanie, ale ak ju nespracuje, prenesie ju na ďalší objekt v reťazi. Cieľom je umožniť viacerým objektom spracovať požiadavku bez nutnosti presne určiť, ktorý objekt ju bude spracovávať a tak dosiahnuť zníženie vzájomnej závislosti medzi odosielateľom a prijímateľom požiadavky.

    Príklad Chain of Responsibility implementácie v Jave

    Teraz si napíšeme program, ktorý bude simulovať schvaľovanie požiadaviek zamestnanca vo firme s použitím návrhového vzoru Chain of Responsibility. Cieľom tohto vzoru je umožniť viacerým objektom spracovať požiadavku bez toho, aby sme presne vedeli, ktorý objekt ju spracuje. Objekty sú zoradené do reťaze a každý objekt v reťazi rozhoduje, či vie spracovať danú požiadavku alebo ju prenesie na ďalší objekt v reťazi.

    V tomto programe existujú tri typy zamestnancov – Zamestnanec, Veduci a Riaditel, každý z nich implementuje abstraktnú triedu SchvalovatelPoziadavky, ktorá obsahuje spoločnú funkcionalitu pre všetkých zamestnancov.

    SchvalovatelPoziadavky.java

    package designpatterns;
    
    public abstract class SchvalovatelPoziadavky {
        String meno;
        SchvalovatelPoziadavky dalsiSchvalovatel;
        private SchvalovatelPoziadavky(){
    
        }
        public SchvalovatelPoziadavky(String meno){
            this.meno = meno;
        }
        public abstract void nastavitDalsiehoSchvalovatela(SchvalovatelPoziadavky dalsiSchvalovatel);
    
        public void posuditPoziadavku(String poziadavka)
        {
            if(this.dalsiSchvalovatel != null)
                this.dalsiSchvalovatel.posuditPoziadavku(poziadavka);
            else
                System.out.println(poziadavka + " - poziadavka bola zamietnuta!");
        }
    }

    Abstraktná trieda SchvalovatelPoziadavky definuje spoločné metódy a obsahuje referenciu na ďalšieho schvaľovateľa v reťazi.

    Zamestnanec.java

    package designpatterns;
    
    public class Zamestnanec extends SchvalovatelPoziadavky {
        public Zamestnanec() {
            super("zamestnanec");
        }
        @Override
        public void nastavitDalsiehoSchvalovatela(SchvalovatelPoziadavky dalsiSchvalovatel) {
            this.dalsiSchvalovatel = dalsiSchvalovatel;
        }
        @Override
        public void posuditPoziadavku(String poziadavka) {
            if(poziadavka == "NAVSTEVA_LEKARA") {
                System.out.println(poziadavka + " - " + meno + " schvalil poziadavku");
            }
            else {
                super.posuditPoziadavku(poziadavka);
            }
        }
    }

    Veduci.java

    package designpatterns;
    
    public class Veduci extends SchvalovatelPoziadavky {
        public Veduci() {
            super("veduci");
        }
        @Override
        public void nastavitDalsiehoSchvalovatela(SchvalovatelPoziadavky dalsiSchvalovatel) {
            this.dalsiSchvalovatel = dalsiSchvalovatel;
        }
        @Override
        public void posuditPoziadavku(String poziadavka) {
            if(poziadavka == "DOVOLENKA") {
                System.out.println(poziadavka + " - " + meno + " schvalil poziadavku");
            }
            else {
                super.posuditPoziadavku(poziadavka);
            }
        }
    }

    Riaditel.java

    package designpatterns;
    public class Riaditel extends SchvalovatelPoziadavky {
        public Riaditel() {
            super("riaditel");
        }
        @Override
        public void nastavitDalsiehoSchvalovatela(SchvalovatelPoziadavky dalsiSchvalovatel) {
            this.dalsiSchvalovatel = dalsiSchvalovatel;
        }
        @Override
        public void posuditPoziadavku(String poziadavka) {
            if(poziadavka == "ZVYSENIE_PLATU") {
                System.out.println(poziadavka + " - " + meno + " schvalil poziadavku");
            }
            else {
                super.posuditPoziadavku(poziadavka);
            }
        }
    }

    Zamestnanec, Veduci, Riaditel sú konkrétne triedy reprezentujúce jednotlivých zamestnancov. Každý z nich môže schvaľovať určité typy požiadaviek, ale ak na niektoré nie je oprávnený, prenesie ich na ďalšieho schvaľovateľa v reťazi.

    Main.java

    import designpatterns.Riaditel;
    import designpatterns.SchvalovatelPoziadavky;
    import designpatterns.Veduci;
    import designpatterns.Zamestnanec;
    
    public class Main {
        public static void main(String[] args) {
            // Clanky retaze
            SchvalovatelPoziadavky zamestnanec = new Zamestnanec();
            SchvalovatelPoziadavky veduci = new Veduci();
            SchvalovatelPoziadavky riaditel = new Riaditel();
            // Vytvorenie retaze zodpovednosti
            zamestnanec.nastavitDalsiehoSchvalovatela(veduci);
            veduci.nastavitDalsiehoSchvalovatela(riaditel);
            // Posudenie poziadaviek
            zamestnanec.posuditPoziadavku("NAVSTEVA_LEKARA");
            zamestnanec.posuditPoziadavku("DOVOLENKA");
            zamestnanec.posuditPoziadavku("ZVYSENIE_PLATU");
            zamestnanec.posuditPoziadavku("FIREMNE_AUTO");
        }
    }

    V metóde main vytvárame reťaz zodpovedností, vytvárame hierarchiu jednotlivých zamestnancov a potom posudzujeme rôzne požiadavky. Každý zamestnanec sa pokúsi schváliť požiadavku. Ak ju nemôže schváliť, deleguje ju na ďalšieho schvaľovateľa v reťazi.

    V metóde main vytvárame reťaz zodpovedností, vytvárame hierarchiu jednotlivých zamestnancov a potom posudzujeme rôzne požiadavky.
    Výstup z tohto príkladu.

    Zhrnutie

    Návrhový vzor Chain of Responsibility sa používa v softvérovom dizajne, keď potrebujeme dosiahnuť flexibilný spôsob spracovania požiadaviek, pričom nechceme vytvárať pevnú väzbu medzi odosielateľom a spracovateľom požiadavky a odovzdávame ich reťazi objektov na spracovanie.

    Pripravili sme pre teba súbory so spomínaným príkladom vo forme kódu, ktorý si môžeš spustiť priamo v Jave. Stiahni si kód Java Chain of Responsibility tu.

    Ak si Java programátor a hľadáš prácu, pozri si naše benefity pre zamestnancov a reaguj na najnovšie pracovné ponuky.

    O autorovi

    Jozef Wagner

    Java Developer Senior

    Viac ako 10 rokov programujem v Jave, momentálne pracujem v msg life Slovakia ako Java programátor senior a pomáham zákazníkom implementovať ich požiadavky do poistného softvéru Life Factory. Vo voľnom čase si rád oddýchnem v lese, prípadne si zahrám nejakú dobrú počítačovú hru.

    Daj nám o sebe vedieť