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).

Was ist das Entwurfsmuster Decorator?

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

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

Es löst das Problem, Instanzen von Klassen zu ändern, ohne dass zusätzliche abgeleitete Klassen erstellt werden müssen, da die neue Funktionalität dynamisch an das Objekt angehängt wird. 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. Er wird hauptsächlich verwendet, wenn wir ein Objekt erweitern müssen (Decorator erweitert die Klasse nicht).

Beispiel einer Decorator-Implementierung in Java

Wir werden nun ein Programm schreiben, das die Verwendung des Decorator-Designmusters demonstriert, um dekorierte Eiscreme mit verschiedenen zusätzlichen Zutaten zu erstellen. Die Schnittstelle IZmrzlina definiert eine vyrobZmrzlinu()-Methode, die von verschiedenen Eiscremes implementiert wird. IZmrzlina.java

package designpatterns;

public interface IZmrzlina {
    public String vyrobZmrzlinu();
}

Die Klasse Ice Cream implementiert die Schnittstelle IZmrzlina und bietet eine grundlegende Implementierung von Eiscreme. Zmrzlina.java

package designpatterns;

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

Die abstrakte Klasse ZmrzlinaDecorator implementiert die Schnittstelle IZmrzlina und enthält eine Referenz auf die IZmrzlina Instanz, die dekoriert werden soll. 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 Dekorator, der Eiscreme mit Schokoladenglasur versieht. Diese Klasse ruft die Methode vyrobZmrzlinu() über die Eiscreme-Referenz auf und überzieht sie mit Schokoladenglasur. 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 Dekorator, der dem Eis zerstoßene Erdnüsse hinzufügt. Ähnlich wie CokoladaDecorator ruft diese Klasse die Methode vyrobZmrzlinu() über eine Eisreferenz 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 Eiscreme-Objekt mit einer Dekorationssequenz. Wir beginnen mit dem ursprünglichen Eis (Zmrzlina), fügen zuerst eine Schokoladensoße (CokoladaDecorator) hinzu und dann gehackte 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());
    }
}

Die Dekoratoren können in beliebiger Reihenfolge kombiniert werden. Diese Flexibilität und dynamische Änderung des Instanzverhaltens zur Laufzeit ist ein wesentlicher 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 verpacken. 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. Laden Sie den Code für den Java 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

Java Developer Senior

Viac ako 10 rokov programujem v Jave, momentálne pracujem v msg life Slovakia ako Java programátor senior a pomáham zákazníkom implementovať ich požiadavky do poistného softvéru Life Factory. Vo voľnom čase si rád oddýchnem v lese, prípadne si zahrám nejakú dobrú počítačovú hru.

Informieren Sie uns über sich