Čtenáři jako vy pomáhají podporovat MUO. Když provedete nákup pomocí odkazů na našich stránkách, můžeme získat provizi přidružené společnosti. Přečtěte si více.

Jedním z nejdůležitějších principů při vývoji softwaru je princip otevřeného a uzavřeného návrhu. Tento princip návrhu zdůrazňuje, že třídy by měly být otevřené pro rozšíření, ale uzavřené pro úpravy. Designový vzor dekoratér ztělesňuje princip otevřeného-zavřeného designu.

Pomocí návrhového vzoru dekoratérů můžete snadno rozšířit třídu tím, že jí dáte nové chování, aniž byste měnili její stávající kód. Vzor dekorátoru to dělá dynamicky za běhu pomocí kompozice. Tento návrhový vzor je známý jako flexibilní alternativa k použití dědičnosti k rozšíření chování.

Jak funguje návrhový vzor dekoratér?

I když dekorační vzor je alternativou k třídní dědictví, do svého návrhu začleňuje některé aspekty dědičnosti. Klíčovým aspektem dekoračního vzoru je, že všechny jeho třídy spolu přímo nebo nepřímo souvisí.

Typický designový vzor dekoratérů má následující strukturu:

instagram viewer

Z výše uvedeného diagramu tříd můžete vidět, že vzor dekoratérů má čtyři hlavní třídy.

Komponent: toto je abstraktní třída (nebo rozhraní), která slouží jako nadtyp pro vzor dekorátoru.

ConcreteComponent: toto jsou objekty, které můžete za běhu ozdobit různými způsoby chování. Dědí z rozhraní komponenty a implementují jeho abstraktní funkce.

Dekoratér: tato třída je abstraktní a má stejný supertyp jako objekt, který bude zdobit. V diagramu tříd uvidíte dva vztahy mezi třídami komponent a dekorátorů. První vztah je vztahem dědičnosti; každý dekoratér je komponent. Druhý vztah je vztah složení; každý dekoratér (nebo obaluje) součást.

Dekoratér betonu: jedná se o jednotlivé dekorátory, které dodávají komponentě specifické chování. Měli byste si uvědomit, že každý dekorátor betonu má proměnnou instance, která obsahuje odkaz na komponentu.

Implementace vzoru Decorator Design Pattern v Javě

Ukázková aplikace pro objednávání pizzy může adekvátně demonstrovat, jak používat vzor dekoratérů k vývoji aplikací. Tato ukázková aplikace pro pizzu umožňuje zákazníkům objednávat pizzy s více polevami. První třídou dekoračního vzoru je rozhraní pizzy:

veřejnostrozhraníPizza{
veřejnostabstraktní Tětiva popis();
veřejnostabstraktnídvojnásobeknáklady();
}

Rozhraní Pizza je třída komponent. Takže z něj můžete vytvořit jednu nebo více konkrétních tříd. Pizza společnost vyrábí dva hlavní typy pizz, založené na jejich těstě. Jeden typ pizzy má kynuté těsto:

veřejnosttřídaDroždíCrustPizzanářadíPizza{
@Přepsat
veřejnost Tětiva popis(){
vrátit se"Těsto na pizzu z droždí";
}

@Přepsat
veřejnostdvojnásobeknáklady(){
vrátit se18.00;
}
}

YeastCrustPizza je první beton třída Java rozhraní Pizza. Dalším dostupným typem pizzy je plochý chléb:

veřejnosttřídaFlatbreadCrustPizzanářadíPizza{
@Přepsat
veřejnost Tětiva popis(){
vrátit se"Těsto na pizzu s plochým chlebem";
}

@Přepsat
veřejnostdvojnásobeknáklady(){
vrátit se15.00;
}
}

Třída FlatbreadCrustPizza je druhou konkrétní komponentou a stejně jako třída YeastCrustPizza implementuje všechny abstraktní funkce rozhraní Pizza.

Dekoratéři

Třída dekoratér je vždy abstraktní, takže z ní nelze přímo vytvořit novou instanci. Je však nutné vytvořit vztah mezi různými dekorátory a komponenty, které budou zdobit.

veřejnostabstraktnítřídaToppingDecoratornářadíPizza{
veřejnost Tětiva popis(){
vrátit se"Neznámá zálivka";
}
}

Třída ToppingDecorator představuje třídu dekoratérů v této ukázkové aplikaci. Nyní může společnost vyrábějící pizzu vytvářet mnoho různých polev (nebo dekoratérů) pomocí třídy ToppingDecorator. Řekněme, že pizza může mít tři různé druhy polevy, konkrétně sýr, feferonky a houby.

Sýrová poleva

veřejnosttřídaSýrrozšiřujeToppingDecorator{
soukromé Pizza pizza;

veřejnostSýr(Pizza){
tento.pizza = pizza;
}

@Přepsat
veřejnost Tětiva popis(){
vrátit se pizza.description() + ", sýrová poleva";
}

@Přepsat
veřejnostdvojnásobeknáklady(){
vrátit sepizza.náklady() + 2.50;
}
}

Poleva na papriky

veřejnosttřídaPepperonirozšiřujeToppingDecorator{
soukromé Pizza pizza;

veřejnostPepperoni(Pizza){
tento.pizza = pizza;
}

@Přepsat
veřejnost Tětiva popis(){
vrátit se pizza.description() + ", Pepperoni Topping";
}

@Přepsat
veřejnostdvojnásobeknáklady(){
vrátit sepizza.náklady() + 3.50;
}
}

Houbová zálivka

veřejnosttřídaHoubarozšiřujeToppingDecorator{
soukromé Pizza pizza;

veřejnostHouba(Pizza){
tento.pizza = pizza;
}

@Přepsat
veřejnost Tětiva popis(){
vrátit se pizza.description() + ", Houbová poleva";
}

@Přepsat
veřejnostdvojnásobeknáklady(){
vrátit sepizza.náklady() + 4.50;
}
}

Nyní máte jednoduchou aplikaci implementovanou pomocí návrhového vzoru dekoratér. Pokud by si zákazník objednal pizzu s kvasnicovou kůrkou se sýrem a feferonkami, testovací kód pro tento scénář bude vypadat takto:

veřejnosttřídaHlavní{
veřejnoststatickýprázdnotahlavní(Řetězec[] argumentů){
Pizza pizza1 = Nový DroždíCrustPizza();
pizza 1 = Nový Pepperoni (pizza1);
pizza 1 = Nový Sýr (pizza1);
System.out.println (pizza1.description() + " $" + pizza1.cost());
}
}

Spuštění tohoto kódu vytvoří v konzole následující výstup:

Jak vidíte, výstup uvádí druh pizzy spolu s její celkovou cenou. Pizza začínala jako pizza s kvasnicovou kůrkou za 18,00 $, ale se vzorem dekoratérů byla aplikace schopna přidat pizze nové funkce a jejich odpovídající cenu. Tím dává pizze nové chování beze změny stávajícího kódu (pizza s kvasnicovou kůrkou).

S dekoračním vzorem můžete také aplikovat stejné chování na objekt tolikrát, kolikrát si přejete. Pokud si zákazník objedná pizzu se vším všudy a nějakým sýrem navíc, můžete aktualizovat hlavní třídu pomocí následujícího kódu, aby to odrážel:

Pizza pizza2 = Nový DroždíCrustPizza();
pizza2 = Nový Pepperoni (pizza2);
pizza2 = Nový Sýr (pizza2);
pizza2 = Nový Sýr (pizza2);
pizza2 = Nový Houba (pizza2);

System.out.println (pizza2.description() + " $" + pizza2.cost());

Aktualizovaná aplikace vytvoří v konzole následující výstup:

Výhody použití dekoračního vzoru

Dvě hlavní výhody použití dekoračního vzoru jsou bezpečnost a flexibilita. Vzor dekorátoru vám umožňuje vyvinout bezpečnější kód tím, že nezasahuje do již existujícího zabezpečeného kódu. Místo toho rozšiřuje stávající kód prostřednictvím kompozice. Účinně brání zavádění nových chyb nebo nezamýšlených vedlejších účinků.

Díky složení má vývojka také velkou flexibilitu při použití dekoračního vzoru. Kdykoli můžete implementovat nový dekorátor a přidat nové chování, aniž byste změnili stávající kód a narušili aplikaci.