Der Decorator-Entwurfsmuster wird verwendet, um die Funktionalität eines Objekts zur Laufzeit zu ändern. Gleichzeitig werden andere Instanzen derselben Klasse dadurch nicht beeinflusst, sodass jedes individuelle Objekt das modifizierte Verhalten erhält. Das Decorator-Entwurfsmuster ist eines der strukturellen Entwurfsmuster (wie das Adaptermuster, das Brückenmuster, das Kompositmuster) und verwendet abstrakte Klassen oder Schnittstellen mit Komposition zur Implementierung.
Decorator-Entwurfsmuster
Wir verwenden Vererbung oder Komposition, um das Verhalten eines Objekts zu erweitern, aber dies geschieht zur Kompilierzeit und ist auf alle Instanzen der Klasse anwendbar. Wir können keine neue Funktionalität hinzufügen oder vorhandenes Verhalten zur Laufzeit entfernen – dies ist der Zeitpunkt, an dem das Dekorierer-Muster ins Spiel kommt. Angenommen, wir möchten verschiedene Arten von Autos implementieren – wir können das Interface Car erstellen, um die Methode assemble zu definieren, und dann können wir ein Basic Car haben, das wir weiter zu einem Sports Car und einem Luxusauto erweitern können. Die Implementierungshierarchie wird wie im folgenden Bild aussehen. Aber wenn wir zur Laufzeit ein Auto erhalten möchten, das sowohl die Eigenschaften eines Sportwagens als auch eines Luxusautos hat, wird die Implementierung komplex, und wenn wir außerdem angeben möchten, welche Funktionen zuerst hinzugefügt werden sollen, wird es noch komplexer. Stellen Sie sich jetzt vor, wir haben zehn verschiedene Arten von Autos, die Implementierungslogik unter Verwendung von Vererbung und Komposition wird unmöglich zu verwalten sein. Um diese Art von Programmiersituation zu lösen, wenden wir das Dekorierer-Muster in Java an. Wir müssen folgende Typen haben, um das Dekorierer-Entwurfsmuster zu implementieren.
-
Komponentenschnittstelle – Die Schnittstelle oder abstrakte Klasse, die die Methoden definiert, die implementiert werden sollen. In unserem Fall wird
Auto
die Komponentenschnittstelle sein.paket com.journaldev.design.decorator; public interface Auto { public void zusammenbauen(); }
-
Komponentenimplementierung – Die grundlegende Implementierung der Komponentenschnittstelle. Wir können die Klasse
BasicCar
als unsere Komponentenimplementierung haben.paket com.journaldev.design.decorator; public class BasicCar implements Auto { @Override public void zusammenbauen() { System.out.print("Grundlegendes Auto."); } }
-
Dekorateur – Die Dekorateur-Klasse implementiert das Komponentenschnittstellen und hat eine HAS-A-Beziehung mit der Komponentenschnittstellen. Die Komponentenvariable sollte für die untergeordneten Dekoratorklassen zugänglich sein, daher machen wir diese Variable geschützt.
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(); } }
-
Konkrete Dekorateure – Erweitern der Basis-Dekorator-Funktionalität und Modifizieren des Komponentenverhaltens entsprechend. Wir können konkrete Dekoratorklassen wie
LuxusAuto
undSportwagen
haben.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(" Hinzufügen von Funktionen des Sportwagens."); } }
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(" Hinzufügen von Funktionen des Luxusautos."); } }
Dekorator-Entwurfsmuster – Klassendiagramm
Dekorator-Entwurfsmuster-Testprogramm
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();
}
}
Beachten Sie, dass das Clientprogramm zur Laufzeit verschiedene Arten von Objekten erstellen und die Ausführungsreihenfolge angeben kann. Die Ausgabe des obigen Testprogramms ist:
Basic Car. Adding features of Sports Car.
*****
Basic Car. Adding features of Luxury Car. Adding features of Sports Car.
Dekorator-Entwurfsmuster – Wichtige Punkte
- Das Dekorator-Entwurfsmuster ist hilfreich, um Laufzeitänderungsfähigkeiten bereitzustellen und daher flexibler zu sein. Es ist einfach zu warten und zu erweitern, wenn die Anzahl der Optionen größer ist.
- Der Nachteil des Dekorator-Entwurfsmusters besteht darin, dass es viele ähnliche Objekte (Dekoratoren) verwendet.
- Das Decorator-Muster wird in Java IO-Klassen häufig verwendet, wie zum Beispiel FileReader, BufferedReader usw.
Source:
https://www.digitalocean.com/community/tutorials/decorator-design-pattern-in-java-example