Návrhové vzory Java (design patterns): Observer

Dnes sa pozrieme na ďalší návrhový vzor Observer (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 Observer?

Observer je návrhový vzor, ktorý nám umožňuje definovať mechanizmus odoberania správ a upozorňovanie všetkých zainteresovaných objektov na akékoľvek udalosti, ktoré nastanú na pozorovanom objekte.

Aký problém návrhový vzor Observer rieši?

Vzor Observer (Pozorovateľ) je návrhový vzor, ktorý rieši problém sledovania zmeny stavu objektu tak, aby všetky jeho závislé objekty (pozorovatelia) boli automaticky informované a aktualizované, keď sa vyskytne zmena v objekte. Tento vzor umožňuje vytvoriť slabé väzby medzi subjektom (objekt, ktorý mení svoj stav) a pozorovateľmi (objekty, ktoré chcú byť informované o zmene).

Pozorovaný objekt – vydavateľ (Publisher) prechádza udalosťami zaujímavými pre iné objekty. Tieto udalosti nastanú, keď zmení svoj stav alebo vykoná nejakú akciu. Vydavatelia obsahujú infraštruktúru predplatného, ​​ktorá umožňuje novým predplatiteľom (Subscribers) pripojiť sa a súčasným predplatiteľom opustiť zoznam.

Keď nastane nová udalosť, vydavateľ prejde zoznam odberov a zavolá metódu upozornenia deklarovanú v rozhraní odberateľa na každom objekte odberateľa. Rozhranie predplatiteľa vo väčšine prípadov pozostáva z jedinej update metódy.

Metóda môže mať niekoľko parametrov, ktoré umožňujú vydavateľovi spolu s aktualizáciou informovať detailnejšie o udalosti. Konkrétni predplatitelia vykonávajú v reakcii na upozornenia vydané vydavateľom vlastné akcie.

Všetky tieto triedy musia implementovať rovnaké rozhranie, takže vydavateľ nie je priamo spojený s konkrétnymi triedami. Predplatitelia zvyčajne potrebujú kontextové informácie na správne spracovanie aktualizácie. Klient vytvorí objekty vydavateľa a predplatiteľa samostatne a potom zaregistruje predplatiteľov na aktualizácie vydavateľa.

Príklad Observer implementácie v Jave

Aby sme si ukázali praktické aplikovanie návrhového vzoru Observer, vytvoríme jednoduchú simuláciu YouTube kanála, kam sa môžu používatelia (odoberatelia) prihlásiť k odberu notifikácií o nových videách na tomto kanáli alebo svoj odber zrušiť.

IOdoberatel.java

package designpatterns;

public interface IOdoberatel {
    void aktualizovat(String sprava);
}

Rozhranie IOdoberatel definuje metódu aktualizovat, ktorú budú konkrétni odoberatelia implementovať. Používa sa na aktualizáciu v prípade nového obsahu.

YouTubePouzivatel.java

package designpatterns;

public class YouTubePouzivatel implements IOdoberatel {
    private String meno;

    public YouTubePouzivatel(String meno) {
        this.meno = meno;
    }

    @Override
    public void aktualizovat(String videoTitul) {
        System.out.println(meno + " dostal/a notifikáciu o novom videu: " + videoTi-tul);
    }

    @Override
    public String toString() {
        return meno;
    }
}
 Trieda YouTubePouzivatel reprezentuje konkrétneho používateľa, ktorý môže prijímať notifikácie o nových videách.

IYoutubeKanal.java

package designpatterns;

public interface IYoutubeKanal {
    void odoberat(IOdoberatel odoberatel);
    void zrusitOdber(IOdoberatel odoberatel);
    void upozornitOdoberatelov(String videoTitul);
}

Rozhranie IYoutubeKanal definuje metódy odoberat, zrusitOdber a upozornitOdoberatelov, ktoré budú konkrétny YouTube kanál implementovať. Používa sa na správu odoberateľov.

YouTubeKanal.java

package designpatterns;

import java.util.ArrayList;
import java.util.List;

public class YouTubeKanal implements IYoutubeKanal {
    private List<IOdoberatel> odoberatelia = new ArrayList<>();
    private String nazovKanala;

    public YouTubeKanal(String nazovKanala) {
        this.nazovKanala = nazovKanala;
    }

    @Override
    public void odoberat(IOdoberatel odoberatel) {
        odoberatelia.add(odoberatel);
        System.out.println(odoberatel + " odoberá " + nazovKanala);
    }

    @Override
    public void zrusitOdber(IOdoberatel odoberatel) {
        odoberatelia.remove(odoberatel);
        System.out.println(odoberatel + " odhlásil/a odber " + nazovKanala);
    }

    @Override
    public void upozornitOdoberatelov(String videoTitul) {
        for(IOdoberatel odoberatel : odoberatelia) {
            odoberatel.aktualizovat(videoTitul);
        }
    }

    public void nahratNoveVideo(String videoTitul) {
        System.out.println("Nové video bolo pridané: " + videoTitul);
        upozornitOdoberatelov(videoTitul);
    }
}

Trieda YouTubeKanal reprezentuje konkrétny YouTube kanál, ktorý môže prihlasovať a odhlasovať odoberateľov a notifikovať ich o nových videách.

Main.java

import designpatterns.IOdoberatel;
import designpatterns.IYoutubeKanal;
import designpatterns.YouTubeKanal;
import designpatterns.YouTubePouzivatel;

public class Main {
    public static void main(String[] args) {
        // Vytvorenie YouTube kanalu
        YouTubeKanal youtubeKanal = new YouTubeKanal("[Programovanie v Jave]");

        // Vytvorenie odoberatelov (subscribers)
        IOdoberatel odoberatel1 = new YouTubePouzivatel("Subscriber1");
        IOdoberatel odoberatel2 = new YouTubePouzivatel("Subscriber2");

        // Nastavenie odberov YouTube kanala
        youtubeKanal.odoberat(odoberatel1);
        youtubeKanal.odoberat(odoberatel2);

        // Pridanie noveho videa, vsetci odoberatelia dostanu upozornenie
        youtubeKanal.nahratNoveVideo("Navrhove vzory v Jave");

        // Odoberatel 1 odhlasi odber
        youtubeKanal.zrusitOdber(odoberatel1);

        // Pridanie dalsieho videa, notifikaciu dostatne len Odoberatel 2
        youtubeKanal.nahratNoveVideo("Java SDK 21");
    }
}

V triede Main simulujeme prevádzku jedného YouTube kanála, kam sa používatelia (odberatelia) môžu prihlásiť a pri pridaní nového videa sú všetci odberatelia notifikovaní. Rovnako vidieť, že po odhlásení z odberu, používateľ prestane dostávať upozornenie na nový obsah.

Výstup z tohto príkladu je:

 

Výstup z príkladu pre návrhový vzor Observer.

Zhrnutie

Vzor Observer sa používa v systémoch, ktoré spracovávajú udalosti, napr. v GUI komponentoch (kliknutie myši na tlačidlo), ale sú užitočné všade tam, kde chceme flexibilne reagovať na zmenu na pozorovanom objekte.

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 Observer tu.

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

 

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ť