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).

Č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ť