Java-Entwurfsmuster (design patterns): Decorator

Heute werfen wir einen Blick auf das nächste Entwurfsmuster (Java design patterns) aus der Kategorie der strukturellen Muster (structural patterns) – Proxy. Entwurfsmuster in dieser Kategorie befassen sich mit Klassenstrukturen wie Vererbung (inheritance) und Komposition (composition).

In diesem Artikel erfährst du:

    Was ist das Entwurfsmuster Decorator?

    Decorator ist ein Entwurfsmuster, das verwendet wird, um bestehenden Objekten dynamisch neue Verantwortlichkeiten oder Funktionen hinzuzufügen (und zu entfernen), ohne das Verhalten anderer Objekte derselben Klasse zu beeinflussen. Das Hinzufügen neuer Funktionalität wird auch als Dekorieren bezeichnet, daher stammt der Name dieses Entwurfsmusters.

    Was für ein Problem löst das Entwurfsmuster Decorator?

    Sie löst das Problem der Änderung von Klasseninstanzen, ohne dass zusätzliche abgeleitete Klassen erstellt werden müssen, da sie die neue Funktionalität dynamisch an das Objekt anhängt. Die Verwendung dieses Musters kann viel effizienter sein als das Erstellen von Unterklassen, da das Verhalten eines Objekts erweitert werden kann, ohne ein komplett neues Objekt zu definieren. Es wird hauptsächlich verwendet, wenn wir ein Objekt erweitern müssen (der Dekorierer erweitert nicht die Klasse).

    Beispiel einer Decorator-Implementierung in Java

    Wir werden nun ein Programm schreiben, das die Verwendung des Entwurfsmusters Decorator demonstriert, um dekorierte Eiscreme mit verschiedenen zusätzlichen Zutaten zu erstellen.

    Das Interface IZmrzlina definiert die Methode vyrobZmrzlinu(), die von verschiedenen Eissorten implementiert wird.

    IZmrzlina.java

    package designpatterns;
    
    public interface IZmrzlina {
        public String vyrobZmrzlinu();
    }
    

    Die Klasse Zmrzlina implementiert das Interface IZmrzlina und bietet eine grundlegende Implementierung der Eiscreme.

    Zmrzlina.java

    package designpatterns;
    
    public class Zmrzlina implements IZmrzlina {
        @Override
        public String vyrobZmrzlinu() {
            return "Zmrzlina";
        }
    }
    

    Die abstrakte Klasse ZmrzlinaDecorator implementiert das Interface IZmrzlina und enthält eine Referenz auf eine Instanz von IZmrzlina, die dekoriert wird. Diese Klasse gibt das Ergebnis der Methode vyrobZmrzlinu() des dekorierten Eises zurück.

    ZmrzlinaDecorator.java

    package designpatterns;
    
    abstract class ZmrzlinaDecorator implements IZmrzlina {
        protected IZmrzlina upravenaZmrzlina;
    
        public ZmrzlinaDecorator(IZmrzlina upravenaZmrzlina) {
            this.upravenaZmrzlina = upravenaZmrzlina;
        }
    
        @Override
        public String vyrobZmrzlinu() {
            return upravenaZmrzlina.vyrobZmrzlinu();
        }
    }
    

    Die Klasse CokoladaDecorator ist ein konkreter Dekorierer, der eine Schokoladensoße zur Eiscreme hinzufügt. Diese Klasse ruft die Methode vyrobZmrzlinu() auf der Referenz zur Eiscreme auf und bedeckt sie mit Schokoladensoße.

    CokoladaDecorator.java

    package designpatterns;
    
    public class CokoladaDecorator extends ZmrzlinaDecorator {
    
            public CokoladaDecorator(IZmrzlina upravenaZmrzlina) {
                super(upravenaZmrzlina);
            }
    
            public String vyrobZmrzlinu() {
                return upravenaZmrzlina.vyrobZmrzlinu() + pridajCokoladu();
            }
    
            private String pridajCokoladu() {
                return ", poliata cokoladovou polevou";
            }
    }
    

    Die Klasse ArasidyDecorator ist ein weiterer konkreter Dekorierer, der zerstoßene Erdnüsse zur Eiscreme hinzufügt. Ähnlich wie der CokoladaDecorator ruft diese Klasse die Methode vyrobZmrzlinu() auf der Referenz zur Eiscreme auf und bestreut sie mit zerstoßenen Erdnüssen.

    ArasidyDecorator.java

    package designpatterns;
    
    public class ArasidyDecorator extends ZmrzlinaDecorator {
    
            public ArasidyDecorator(IZmrzlina upravenaZmrzlina) {
                super(upravenaZmrzlina);
            }
    
            public String vyrobZmrzlinu() {
                return upravenaZmrzlina.vyrobZmrzlinu() + pridajArasidy();
            }
    
            private String pridajArasidy() {
                return ", posypana drvenymi arasidami";
            }
    }
    

    In der Methode main() erstellen wir ein konkretes Eisobjekt mit einer Sequenz von Dekorationen. Wir beginnen mit der ursprünglichen Eiscreme (Zmrzlina), fügen zuerst die Schokoladensoße (CokoladaDecorator) hinzu und anschließend die zerstoßenen Erdnüsse (ArasidyDecorator).

    Main.java

    import designpatterns.*;
    
    public class Main {
        public static void main(String[] args) {
            IZmrzlina zmrzlina = new ArasidyDecorator(new CokoladaDecorator(new Zmrzlina()));
            System.out.println(zmrzlina.vyrobZmrzlinu());
        }
    }
    

    Dekoratoren können in beliebiger Reihenfolge kombiniert werden. Diese Flexibilität und dynamische Änderung des Instanzverhaltens zur Laufzeit ist ein grundlegender Vorteil des Entwurfsmusters Decorator.

    Dekoratoren können in beliebiger Reihenfolge kombiniert werden. Diese Flexibilität und dynamische Änderung des Instanzverhaltens zur Laufzeit ist ein grundlegender Vorteil des Entwurfsmusters Decorator.
    Ausgabe des Beispiels für das Entwurfsmuster Decorator.

    Zusammenfassung

    Das Entwurfsmuster Decorator wird verwendet, wenn wir einer Schnittstelle dynamische Verantwortung hinzufügen müssen, indem wir den ursprünglichen Code einpacken. Wenn wir durch einfache Vererbung neue Funktionen hinzufügen würden, würden alle Objekte diese Funktionen erben, auch diejenigen, die sie nicht benötigen. Dies können wir vermeiden, indem wir dieses Muster verwenden.

    Wir haben die Dateien mit dem obigen Beispiel in Form von Code vorbereitet, den du direkt in Java ausführen kannst. Lade den Java Code Decorator hier herunter.

    Beherrschst du die Programmiersprache Java? Wenn du als Java Entwickler auf der Suche nach einem Job bist, informiere dich über unsere Mitarbeiterbenefits und reagiere auf unsere aktuellen Stellenangebote.

    Über den Autor

    Jozef Wagner

    Leitender Java-Entwickler

    Ich programmiere seit mehr als 10 Jahren in Java, arbeite derzeit bei msg life Slovakia als leitender Java-Programmierer und helfe Kunden bei der Umsetzung ihrer Anforderungen in die Versicherungssoftware Life Factory. In meiner Freizeit entspanne ich gerne in den Bergen oder spiele ein gutes Computerspiel.

    Informieren Sie uns über sich