Један од најважнијих принципа у развоју софтвера је принцип отворено-затвореног дизајна. Овај принцип дизајна наглашава да класе треба да буду отворене за проширење, али затворене за модификацију. Образац дизајна декоратера оличава принцип отворено-затвореног дизајна.
Са шаблоном дизајна декоратера, можете лако проширити класу тако што ћете јој дати ново понашање без мењања постојећег кода. Узорак декоратера то ради динамички током рада, користећи композицију. Овај образац дизајна је познат као флексибилна алтернатива коришћењу наслеђивања за проширење понашања.
Како функционише шаблон дизајна декоратера?
Иако је шаблон декорације алтернатива класно наслеђе, он заиста укључује неке аспекте наслеђивања у свој дизајн. Кључни аспект шаблона декоратера је да су све његове класе повезане, било директно или индиректно.
Типичан шаблон дизајна декоратера има следећу структуру:
Из горњег дијаграма класа можете видети да шаблон декоратора има четири главне класе.
Саставни део: ово је апстрактна класа (или интерфејс), која служи као супертип за шаблон декоратора.
Бетонска компонента: ово су објекти које можете украсити различитим понашањима током рада. Они наслеђују интерфејс компоненте и имплементирају његове апстрактне функције.
декоратер: ова класа је апстрактна и има исти супертип као и објекат који ће украсити. У дијаграму класа видећете два односа између класа компоненти и декоратора. Прва веза је наследна; сваки декоратер је саставни део. Други однос је однос композиције; сваки декоратер има (или омота а) компоненту.
ЦонцретеДецоратор: то су појединачни декоратери који компоненти дају специфично понашање. Требало би да приметите да сваки конкретни декоратор има променљиву инстанце која садржи референцу на компоненту.
Имплементација шаблона дизајна декоратера у Јави
Пример апликације за наручивање пице може на адекватан начин показати како се користи шаблон декоратера за развој апликација. Ова апликација за узорке пице омогућава купцима да наруче пице са више прелива. Прва класа шаблона декоратера је интерфејс за пицу:
јавностиинтерфејспица{
јавностиапстрактан Низ Опис();
јавностиапстрактандуплотрошак();
}
Пизза интерфејс је класа компоненти. Дакле, од њега можете креирати једну или више конкретних класа. Компанија за пице прави две главне врсте пица, на основу њиховог теста. Једна врста пице има тесто од квасца:
јавностикласаИеастЦрустПиззаимплементирапица{
@Прегазити
јавности Низ Опис(){
повратак"Тесто за пицу направљено са квасцем";
}
@Прегазити
јавностидуплотрошак(){
повратак18.00;
}
}
ИеастЦрустПизза је први бетон Јава класа интерфејса Пизза. Друга доступна врста пице је сомун:
јавностикласаФлатбреадЦрустПиззаимплементирапица{
@Прегазити
јавности Низ Опис(){
повратак"Тесто за пицу направљено од сомуна";
}
@Прегазити
јавностидуплотрошак(){
повратак15.00;
}
}
Класа ФлатбреадЦрустПизза је друга конкретна компонента и, као и класа ИеастЦрустПизза, имплементира све апстрактне функције Пизза интерфејса.
Тхе Децораторс
Класа декоратера је увек апстрактна, тако да не можете креирати нову инстанцу директно из ње. Али неопходно је успоставити однос између различитих декоратера и компоненти које ће они украшавати.
јавностиапстрактанкласаТоппингДецораторимплементирапица{
јавности Низ Опис(){
повратак"Непознати прелив";
}
}
Класа ТоппингДецоратор представља класу декоратера у овом узорку апликације. Сада пизза компанија може да креира много различитих прелива (или декоратора), користећи класу ТоппингДецоратор. Рецимо да пица може имати три различите врсте прелива, наиме сир, фефероне и печурке.
Цхеесе Топпинг
јавностикласаСирпротежеТоппингДецоратор{
приватни Пизза пизза;јавностиСир(пица пица){
ово.пица = пица;
}@Прегазити
јавности Низ Опис(){
повратак пизза.десцриптион() + ", прелив од сира";
}
@Прегазити
јавностидуплотрошак(){
повратакпица.цост() + 2.50;
}
}
Прелив феферона
јавностикласаПеперонипротежеТоппингДецоратор{
приватни Пизза пизза;јавностиПеперони(пица пица){
ово.пица = пица;
}@Прегазити
јавности Низ Опис(){
повратак пизза.десцриптион() + ", прелив од феферона";
}
@Прегазити
јавностидуплотрошак(){
повратакпица.цост() + 3.50;
}
}
Прелив од печурака
јавностикласаМусхроомпротежеТоппингДецоратор{
приватни Пизза пизза;јавностиМусхроом(пица пица){
ово.пица = пица;
}
@Прегазити
јавности Низ Опис(){
повратак пизза.десцриптион() + ", прелив од печурака";
}
@Прегазити
јавностидуплотрошак(){
повратакпица.цост() + 4.50;
}
}
Сада имате једноставну апликацију имплементирану помоћу шаблона дизајна декоратера. Ако би купац наручио пицу са кором од квасца са сиром и феферонима, тестни код за тај сценарио ће изгледати овако:
јавностикласаГлавни{
јавностистатичнапразнинаглавни(Стринг[] аргументи){
Пица пица1 = Нова ИеастЦрустПизза();
пизза1 = Нова Феферони (пица1);
пизза1 = Нова Сир (пица1);
Систем.оут.принтлн (пизза1.десцриптион() + " $" + пизза1.цост());
}
}
Покретање овог кода ће произвести следећи излаз у конзоли:
Као што видите, излаз наводи врсту пице заједно са њеном укупном ценом. Пица је почела као пица са кором од квасца за 18,00 долара, али са шаблоном декорације, апликација је могла да дода нове карактеристике и њихову одговарајућу цену пици. Дакле, дајући пици ново понашање без промене постојећег кода (пица са кором квасца).
Са шаблоном декоратера, такође можете применити исто понашање на објекат онолико пута колико желите. Ако купац наручи пицу са свиме на њој и мало додатног сира, можете ажурирати главну класу следећим кодом како бисте то одразили:
Пица пизза2 = Нова ИеастЦрустПизза();
пизза2 = Нова Феферони (пица2);
пизза2 = Нова Сир (пица2);
пизза2 = Нова Сир (пица2);
пизза2 = Нова Печурке (пица2);Систем.оут.принтлн (пизза2.десцриптион() + " $" + пизза2.цост());
Ажурирана апликација ће произвести следећи излаз у конзоли:
Предности коришћења шаблона за дизајн декоратера
Две главне предности коришћења шаблона за дизајн декоратера су сигурност и флексибилност. Узорак декоратера вам омогућава да развијете безбеднији код не мешајући се са већ постојећим безбедним кодом. Уместо тога, проширује постојећи код кроз композицију. Ефикасно спречава увођење нових грешака или нежељених нежељених ефеката.
Због композиције програмер такође има велику флексибилност када користи шаблон декорације. У било ком тренутку можете да примените нови декоратор да бисте додали ново понашање, без мењања постојећег кода и ометања апликације.