Decorator ontwerppatroon wordt gebruikt om de functionaliteit van een object op runtime te wijzigen. Tegelijkertijd zullen andere instanties van dezelfde klasse hierdoor niet worden beïnvloed, zodat elk individueel object het gewijzigde gedrag krijgt. Decorator ontwerppatroon is een van de structurele ontwerppatronen (zoals Adapterpatroon, Bridgepatroon, Samengesteld patroon) en maakt gebruik van abstracte klassen of interfaces met compositie om te implementeren.
Decorator Ontwerppatroon
We gebruiken overerving of compositie om het gedrag van een object uit te breiden, maar dit gebeurt op compileertijd en is van toepassing op alle instanties van de klasse. We kunnen geen nieuwe functionaliteit toevoegen of bestaand gedrag verwijderen op runtime – dit is waar het Decorator-patroon in beeld komt. Stel dat we verschillende soorten auto’s willen implementeren – we kunnen een interface Car maken om de assemble-methode te definiëren en dan kunnen we een basisauto hebben, die we verder kunnen uitbreiden naar een sportauto en een luxe auto. De implementatiehiërarchie zal eruitzien zoals in onderstaande afbeelding. Maar als we op runtime een auto willen krijgen die zowel de functies van een sportauto als een luxe auto heeft, wordt de implementatie complexer. En als we vervolgens willen specificeren welke functies eerst moeten worden toegevoegd, wordt het nog ingewikkelder. Stel je nu voor dat we tien verschillende soorten auto’s hebben, de implementatielogica met overerving en compositie zou onmogelijk te beheren zijn. Om dit soort programmeersituaties op te lossen, passen we het decoratorpatroon toe in Java. We moeten de volgende typen hebben om het decoratorontwerppatroon te implementeren.
-
Component Interface – De interface of abstracte klasse die de methoden definieert die zullen worden geïmplementeerd. In ons geval zal
Car
de componentinterface zijn.package com.journaldev.design.decorator; public interface Car { public void assemble(); }
-
Component Implementatie – De basisimplementatie van de componentinterface. We kunnen de klasse
BasicCar
als onze componentimplementatie hebben.package com.journaldev.design.decorator; public class BasicCar implements Car { @Override public void assemble() { System.out.print("Basisauto."); } }
-
Decorator – De Decorator-klasse implementeert de componentinterface en heeft een HEEFT-EEN-relatie met de componentinterface. De componentvariabele moet toegankelijk zijn voor de kinddecoratorklassen, dus we maken deze variabele beschermd.
package com.journaldev.design.decorator; public class CarDecorator implements Car { protected Car car; public CarDecorator(Car c){ this.car=c; } @Override public void assemble() { this.car.assemble(); } }
-
Concrete Decorators – Het uitbreiden van de basisdecoratorfunctionaliteit en het aanpassen van het componentgedrag dienovereenkomstig. We kunnen concrete decoratorklassen hebben zoals
LuxuryCar
enSportsCar
.package com.journaldev.design.decorator; public class SportsCar extends CarDecorator { public SportsCar(Car c) { super(c); } @Override public void assemble(){ super.assemble(); System.out.print(" Toevoegen van kenmerken van een sportwagen."); } }
package com.journaldev.design.decorator; public class LuxuryCar extends CarDecorator { public LuxuryCar(Car c) { super(c); } @Override public void assemble(){ super.assemble(); System.out.print(" Toevoegen van kenmerken van een luxe auto."); } }
Decorator Ontwerppatroon – Klassediagram
Testprogramma voor Decorator Ontwerppatroon
package com.journaldev.design.test;
import com.journaldev.design.decorator.BasicCar;
import com.journaldev.design.decorator.Car;
import com.journaldev.design.decorator.LuxuryCar;
import com.journaldev.design.decorator.SportsCar;
public class DecoratorPatternTest {
public static void main(String[] args) {
Car sportsCar = new SportsCar(new BasicCar());
sportsCar.assemble();
System.out.println("\n*****");
Car sportsLuxuryCar = new SportsCar(new LuxuryCar(new BasicCar()));
sportsLuxuryCar.assemble();
}
}
Let op dat het clientprogramma verschillende soorten objecten kan maken tijdens runtime en ze ook de volgorde van uitvoering kunnen specificeren. De uitvoer van bovenstaand testprogramma is:
Basic Car. Adding features of Sports Car.
*****
Basic Car. Adding features of Luxury Car. Adding features of Sports Car.
Decorator Ontwerppatroon – Belangrijke punten
- Het decorator ontwerppatroon is nuttig voor het bieden van runtime modificatiemogelijkheden en is daardoor flexibeler. Het is eenvoudig te onderhouden en uit te breiden wanneer het aantal keuzes groter is.
- Het nadeel van het decorator ontwerppatroon is dat het veel vergelijkbare objecten (decorators) gebruikt.
- Het Decorator patroon wordt veel gebruikt in Java IO klassen, zoals FileReader, BufferedReader enzovoort.
Source:
https://www.digitalocean.com/community/tutorials/decorator-design-pattern-in-java-example