Bralci, kot ste vi, pomagajo podpirati MUO. Ko opravite nakup prek povezav na našem spletnem mestu, lahko zaslužimo partnersko provizijo. Preberi več.

Eno najpomembnejših načel pri razvoju programske opreme je odprto-zaprto načelo oblikovanja. To načelo načrtovanja poudarja, da morajo biti razredi odprti za razširitev, vendar zaprti za spreminjanje. Oblikovalski vzorec dekoraterja uteleša načelo oblikovanja odprto-zaprto.

Z oblikovalskim vzorcem dekoraterja lahko preprosto razširite razred tako, da mu daste novo vedenje, ne da bi spremenili njegovo obstoječo kodo. Vzorec dekoraterja to počne dinamično med izvajanjem z uporabo kompozicije. Ta načrtovalni vzorec je znan kot prilagodljiva alternativa uporabi dedovanja za razširitev vedenja.

Kako deluje oblikovalski vzorec dekoraterja?

Čeprav je dekoraterski vzorec alternativa razredno dedovanje, v svojo zasnovo vključuje nekatere vidike dedovanja. Ključni vidik vzorca dekoraterja je, da so vsi njegovi razredi neposredno ali posredno povezani.

Tipičen oblikovalski vzorec dekoraterja ima naslednjo strukturo:

Iz zgornjega diagrama razredov lahko vidite, da ima vzorec dekoraterja štiri glavne razrede.

Komponenta: to je abstraktni razred (ali vmesnik), ki služi kot supertip za vzorec dekoraterja.

Betonska komponenta: to so predmeti, ki jih lahko okrasite z različnimi vedenji med izvajanjem. Podedujejo vmesnik komponente in izvajajo njegove abstraktne funkcije.

dekorater: ta razred je abstrakten in ima isti nadtip kot predmet, ki ga bo okrasil. V diagramu razredov boste videli dve razmerji med razredoma komponente in dekoratorja. Prvo razmerje je dedovanje; vsak dekorater je komponento. Drugo razmerje je razmerje sestave; vsak dekorater ima (ali ovije) komponento.

ConcreteDecorator: to so posamezni dekoraterji, ki dajejo komponenti specifično vedenje. Upoštevati morate, da ima vsak betonski dekorater spremenljivko primerka, ki vsebuje sklic na komponento.

Implementacija oblikovalskega vzorca dekoratorja v Javi

Vzorec aplikacije za naročanje pice lahko ustrezno pokaže, kako uporabiti vzorec dekoraterja za razvoj aplikacij. Ta vzorčna aplikacija za pico strankam omogoča naročanje pic z več prelivi. Prvi razred vzorca dekoraterja je vmesnik za pico:

javnostivmesnikPizza{
javnostipovzetek Vrvica opis();
javnostipovzetekdvojnostroški();
}

Vmesnik Pizza je razred komponente. Torej lahko iz njega ustvarite enega ali več konkretnih razredov. Pizzerija izdeluje dve glavni vrsti pic na podlagi njihovega testa. Ena vrsta pice ima kvašeno testo:

javnostirazredYeastCrustPizzapripomočkePizza{
@Preglasi
javnosti Vrvica opis(){
vrnitev"Kvašeno testo za pico";
}

@Preglasi
javnostidvojnostroški(){
vrnitev18.00;
}
}

YeastCrustPizza je prvi beton Java razred vmesnika Pizza. Druga vrsta pice, ki je na voljo, je pecivo:

javnostirazredFlatbreadCrustPizzapripomočkePizza{
@Preglasi
javnosti Vrvica opis(){
vrnitev"Testo za pico iz lepinke";
}

@Preglasi
javnostidvojnostroški(){
vrnitev15.00;
}
}

Razred FlatbreadCrustPizza je druga konkretna komponenta in tako kot razred YeastCrustPizza implementira vse abstraktne funkcije vmesnika Pizza.

Dekoraterji

Razred dekoraterja je vedno abstrakten, zato ne morete ustvariti novega primerka neposredno iz njega. Vendar je treba vzpostaviti razmerje med različnimi dekoraterji in komponentami, ki jih bodo okrasili.

javnostipovzetekrazredToppingDecoratorpripomočkePizza{
javnosti Vrvica opis(){
vrnitev"Neznan preliv";
}
}

Razred ToppingDecorator predstavlja razred dekoraterja v tej vzorčni aplikaciji. Zdaj lahko picerija ustvari veliko različnih prelivov (ali okraskov) z uporabo razreda ToppingDecorator. Recimo, da ima pica lahko tri različne vrste prelivov, in sicer sir, feferoni in gobe.

Sirni preliv

javnostirazredsirse raztezaToppingDecorator{
zasebno Pizza pizza;

javnostisir(Pica pica){
to.pizza = pica;
}

@Preglasi
javnosti Vrvica opis(){
vrnitev pizza.description() + ", sirni preliv";
}

@Preglasi
javnostidvojnostroški(){
vrnitevpica.strošek() + 2.50;
}
}

Preliv iz feferoni

javnostirazredFeferonise raztezaToppingDecorator{
zasebno Pizza pizza;

javnostiFeferoni(Pica pica){
to.pizza = pica;
}

@Preglasi
javnosti Vrvica opis(){
vrnitev pizza.description() + ", feferoni preliv";
}

@Preglasi
javnostidvojnostroški(){
vrnitevpica.strošek() + 3.50;
}
}

Gobov preliv

javnostirazredGobase raztezaToppingDecorator{
zasebno Pizza pizza;

javnostiGoba(Pica pica){
to.pizza = pica;
}

@Preglasi
javnosti Vrvica opis(){
vrnitev pizza.description() + ", gobji preliv";
}

@Preglasi
javnostidvojnostroški(){
vrnitevpica.strošek() + 4.50;
}
}

Zdaj imate preprosto aplikacijo, implementirano z oblikovalskim vzorcem dekoraterja. Če bi stranka naročila pico s kvašeno skorjo s sirom in feferoni, bo testna koda za ta scenarij videti takole:

javnostirazredGlavni{
javnostistatičnaprazninaglavni(Argumenti niza[]){
Pica pizza1 = novo Kvasna skorjaPizza();
pica1 = novo Feferoni (pica1);
pica1 = novo Sir (pica1);
System.out.println (pizza1.description() + " $" + pizza1.cost());
}
}

Če zaženete to kodo, bo v konzoli prikazan naslednji izhod:

Kot lahko vidite, izhod navaja vrsto pice skupaj z njeno skupno ceno. Pica se je začela kot pica s kvašeno skorjico za 18,00 $, vendar je z vzorcem dekoraterja aplikacija lahko pici dodala nove funkcije in njihovo ustrezno ceno. Tako da pici novo obnašanje brez spreminjanja obstoječe kode (pica s kvašeno skorjo).

Z vzorcem dekoraterja lahko enako vedenje uporabite za predmet, kolikorkrat želite. Če stranka naroči pico z vsem, kar je na njej, in nekaj dodatnega sira, lahko posodobite glavni razred z naslednjo kodo, da to odraža:

Pica pizza2 = novo Kvasna skorjaPizza();
pica2 = novo Feferoni (pica2);
pica2 = novo Sir (pica2);
pica2 = novo Sir (pica2);
pica2 = novo gobe (pica2);

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

Posodobljena aplikacija bo v konzoli ustvarila naslednje rezultate:

Prednosti uporabe oblikovalskega vzorca dekoraterja

Dve glavni prednosti uporabe oblikovalskega vzorca dekoraterja sta varnost in prilagodljivost. Vzorec dekoraterja vam omogoča, da razvijete bolj varno kodo, tako da ne posegate v že obstoječo varno kodo. Namesto tega razširja obstoječo kodo s sestavo. Učinkovito preprečuje vnos novih hroščev ali nenamernih stranskih učinkov.

Zaradi sestave ima razvijalec tudi veliko prilagodljivosti pri uporabi vzorca dekoraterja. Kadar koli lahko implementirate nov dekorater, da dodate novo vedenje, ne da bi spremenili obstoječo kodo in prekinili aplikacijo.