Das Decorator-Muster in Java

1. Überblick

  • Ein Decorator-Muster kann verwendet werden, um zusätzliche Zuständigkeiten entweder statisch oder dynamisch an ein Objekt anzuhängen. ** Ein Decorator bietet eine erweiterte Schnittstelle zum ursprünglichen Objekt.

Bei der Implementierung dieses Musters bevorzugen wir die Komposition einer Vererbung - so dass wir den Aufwand für die Unterklassen für jedes Dekorationselement immer wieder reduzieren können. Die Rekursion, die mit diesem Entwurf verbunden ist, kann verwendet werden, um unser Objekt so oft zu dekorieren, wie wir es benötigen.

2. Musterbeispiel für Dekorateur

Angenommen, wir haben ein Christbaumobjekt und möchten es dekorieren. Die Dekoration verändert das Objekt selbst nicht; Es ist nur so, dass wir zusätzlich zum Weihnachtsbaum einige Dekorationsartikel wie Girlande, Lametta, Baumkronen, Bubble Lights usw. hinzufügen:

  • Für dieses Szenario befolgen wir die ursprünglichen Design- und Benennungskonventionen von Gang of Four. ** Zuerst erstellen wir eine ChristmasTree -Schnittstelle und deren Implementierung:

public interface ChristmasTree {
    String decorate();
}

Die Implementierung dieser Schnittstelle wird folgendermaßen aussehen:

public class ChristmasTreeImpl implements ChristmasTree {

    @Override
    public String decorate() {
        return "Christmas tree";
    }
}

Wir erstellen jetzt eine abstrakte TreeDecorator -Klasse für diesen Baum. Dieser Dekorateur implementiert die ChristmasTree -Schnittstelle und enthält dasselbe Objekt. Die implementierte Methode von derselben Schnittstelle ruft einfach die Methode decorate () von unserer Schnittstelle auf:

public abstract class TreeDecorator implements ChristmasTree {
    private ChristmasTree tree;

   //standard constructors
    @Override
    public String decorate() {
        return tree.decorate();
    }
}

Wir erstellen jetzt ein Dekorationselement. Diese Dekorierer erweitern unsere abstrakte TreeDecorator-Klasse und ändern ihre decorate () __-Methode entsprechend unserer Anforderung:

public class BubbleLights extends TreeDecorator {

    public BubbleLights(ChristmasTree tree) {
        super(tree);
    }

    public String decorate() {
        return super.decorate() + decorateWithBubbleLights();
    }

    private String decorateWithBubbleLights() {
        return " with Bubble Lights";
    }
}

Für diesen Fall gilt Folgendes:

@Test
public void whenDecoratorsInjectedAtRuntime__thenConfigSuccess() {
    ChristmasTree tree1 = new Garland(new ChristmasTreeImpl());
    assertEquals(tree1.decorate(),
      "Christmas tree with Garland");

    ChristmasTree tree2 = new BubbleLights(
      new Garland(new Garland(new ChristmasTreeImpl())));
    assertEquals(tree2.decorate(),
      "Christmas tree with Garland with Garland with Bubble Lights");
}

Beachten Sie, dass im ersten tree1 -Objekt nur mit einem Garland dekoriert wird, während das andere tree2 -Objekt mit einem BubbleLights und zwei Garlands dekoriert wird. Dieses Muster gibt uns die Flexibilität, so viele Dekorateure zur Laufzeit hinzuzufügen, wie wir möchten.

4. Fazit

In diesem Artikel haben wir uns das Designmuster des Dekorateurs angesehen. Dies ist eine gute Wahl in den folgenden Fällen:

  • Wenn wir das Verhalten oder den Zustand von hinzufügen, verbessern oder sogar entfernen möchten

Objekte ** Wenn wir nur die Funktionalität eines einzelnen Objekts von ändern möchten

Klasse und andere unverändert lassen

Der vollständige Quellcode für dieses Beispiel ist verfügbar unter over auf GitHub .