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

Dnes sa pozrieme na ďalší návrhový vzor Bridge (java design patterns) z kategórie štrukturálnych vzorov (structural patterns). Návrhové vzory v tejto kategórii sa zaoberajú štruktúrou triedy, ako je dedičnosť (inheritance) a kompozícia (composition).

Prečítaj si o ďalších design patterns – seriál návrhových vzorov:

Návrhový vzor Bridge (Most) je návrhový vzor používaný v softvérovom inžinierstve, ktorý má odčleniť abstrakciu od implementácie, aby sa obe časti mohli nezávisle od seba meniť. Vzor Bridge pritom používa zapuzdrenie, agregáciu a môže použiť dedičnosť na rozdelenie zodpovedností do rôznych tried.

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

Vzor Bridge rieši problém, keď chceme, aby hierarchia tried mala dve nezávislé dimenzie rozšíriteľnosti – jednu pre abstrakciu a druhú pre implementáciu.

Hlavným cieľom vzoru Bridge je umožniť klientom vybrať a kombinovať rôzne implementácie s rôznymi abstrakciami bez toho, aby sa menila ich hierarchia tried. Týmto spôsobom môžeme dosiahnuť väčšiu flexibilitu a znovu použiteľnosť v kóde.

Použitie návrhového vzoru Bridge nám teda umožní, aby abstrakcia a jej implementácia boli definované a rozširované nezávisle od seba. Okrem toho nám umožní aj vyhnúť sa spojeniu medzi abstrakciou a jej implementáciou v čase kompilácie, aby následne bolo možné implementáciu vyberať za behu programu.

Príklad Bridge implementácie v Jave

Teraz si ukážeme ako implementovať vzor Bridge v Jave. V tomto príklade naprogramujeme možnosť nakupovania v rôznych typoch obchodov (napr. internetový obchod, kamenný obchod), pomocou rôznych spôsobov platieb (napr. kreditná karta, PayPal). Pre abstrakciu použijeme abstraktnú triedu Obchod a pre rôzne implementácie platieb rozhranie SposobPlatby.

Oddelíme abstrakciu (Abstraction) od jej implementácie (Implementor) ich umiestnením do samostatných hierarchií tried. Následne implementujeme Abstraction delegovaním na Implementor objekt.

Abstrakcia Obchod reprezentuje rôzne typy obchodov (napr. kamenný obchod, internetový obchod).

Obchod.java

package designpatterns;

// Abstrakcia - typ obchodu
abstract public class Obchod {
    protected SposobPlatby sposobPlatby;

    public Obchod(SposobPlatby sposobPlatby) {
        this.sposobPlatby = sposobPlatby;
    }

    public abstract void nakup(float suma);
}

Konkrétnejšie abstrakcie (KamennyObchod a InternetovyObchod) reprezentujú rôzne typy obchodov, ktoré môžu vykonávať nákupy a používať SposobPlatby na spracovanie platieb.

KamennyObchod.java

package designpatterns;

// Konkrétnejšia abstrakcia obchodu - kamenný obchod
public class KamennyObchod extends Obchod {
    public KamennyObchod(SposobPlatby sposobPlatby) {
        super(sposobPlatby);
    }

    public void nakup(float suma) {
        System.out.println("Nákup v kamennom obchode.");
        sposobPlatby.spracujPlatbu(suma);
    }
}

InternetovyObchod.java

package designpatterns;

// Konkrétnejšia abstrakcia obchodu - internetový obchod
public class InternetovyObchod extends Obchod {
    public InternetovyObchod(SposobPlatby sposobPlatby) {
        super(sposobPlatby);
    }

    public void nakup(float suma) {
        System.out.println("Nákup v internetovom obchode.");
        sposobPlatby.spracujPlatbu(suma);
    }
}

Implementátor SposobPlatby reprezentuje rôzne spôsoby platby (napr. kreditná karta, PayPal).

SposobPlatby.java

package designpatterns;

// Implementátor - rozhranie pre spôsob platby
public interface SposobPlatby {
    void spracujPlatbu(float suma);
}

Konkrétne implementácie (PlatbaKreditnouKartou a PlatbaPayPal) poskytujú špecifické implementácie spôsobov platby.

PlatbaKreditnouKartou.java

package designpatterns;

// Konkrétna implementácia – platba kreditnou kartou
public class PlatbaKreditnouKartou implements SposobPlatby {
    private String cisloKarty;

    public PlatbaKreditnouKartou(String cisloKarty) {
        this.cisloKarty = cisloKarty;
    }

    public void spracujPlatbu(float suma) {
        System.out.println("Spracováva sa platba kreditnou kartou vo výške " + suma + "€ s číslom karty " + cisloKarty  + ".");
    }
}

V triede Main vytvárame inštancie rôznych typov obchodov s rôznymi spôsobmi platby a vykonávame nákupy. Vzor Bridge nám umožňuje meniť a kombinovať spôsoby platby a typy obchodov bez zmeny hierarchie triedy Obchod.

Main.java

import designpatterns.*;

public class Main {
    public static void main(String[] args) {
        SposobPlatby platbaKreditnouKartou = new PlatbaKreditnouKartou("1234-5678-9012-3456");
        SposobPlatby platbaPayPal = new PlatbaPayPal("mojpaypal@email.com");

        Obchod internetovyObchod = new InternetovyObchod(platbaKreditnouKartou);
        Obchod kamennyObchod = new KamennyObchod(platbaPayPal);

        internetovyObchod.nakup(100.0f);
        kamennyObchod.nakup(50.0f);
    }
}

Výstup z tohto príkladu je:

výstup v java z príkladu návrhový vzor bridge
návrhový vzor Bridge – výstup príkladu

Zhrnutie

Návrhový vzor Bridge sa používa v situácii, keď je potrebné rozdeliť abstrakciu od implementácie, aby sme ich mohli nezávisle meniť.

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

Ovládaš programovací jazyk Java? Ak hľadáš prácu napr. ako Java programátor, pozri si naše firemné benefity 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ť