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ť