Ich habe die folgende Schnittstelle.
PowerSwitch.java
%Vor%Die obige Schnittstelle sollte aus dem Minimum an Methoden bestehen, aus denen jede andere Funktionalität abgeleitet werden kann, um das Hinzufügen weiterer PowerSwitch-Implementierungen so einfach wie möglich zu machen.
Ich möchte der PowerSwitch-Schnittstelle zur Laufzeit Funktionen hinzufügen (was Dekoratoren tun), indem ich eine Klasse erstelle, die eine Zusammensetzung einer PowerSwitch-Instanz enthält und neue Methoden hinzufügt, wie die beiden toggleOnOff () Methoden unten. Auf diese Weise muss ich die beiden Umschaltmethoden nur einmal implementieren und sie wird auf alle PowerSwitch-Implementierungen angewendet.
Wird dies als eine gute / schlechte Praxis angesehen? Wenn schlecht, irgendwelche anderen Empfehlungen?
Es entspricht nicht wirklich dem Decorator-Muster, da es zusätzliche Methoden hinzufügt. Ist es ein Strategie- oder ein Kompositionsmuster? Oder hat es einen anderen Musternamen? Gibt es so etwas wie einen "Interface Decorator"?
PowerSwitchDecorator.java
%Vor% Jeder Code, der die Methoden toggleOnOff(int)
oder toggleOnOff()
verwenden möchte, benötigt eine Instanz von PowerSwitchDecorator
, nicht PowerSwitch
. Diese Art besiegt den Zweck eines Dekorators, der für den Kunden transparent sein sollte.
Wenn Sie möchten, dass alle Implementierungen über diese Methoden verfügen, sollten Sie sie in die Schnittstelle PowerSwitch
einfügen.
Dann könnten Sie, wie @Ani vorschlägt, das obige PowerSwitchDecorator
ändern, um PowerSwitch
zu erweitern, damit Sie dies tun können:
Jetzt haben Sie eine Variable vom Typ PowerSwitch
mit den Fähigkeiten von PowerSwitchDecorator
.
BEARBEITEN: Beachten Sie, dass Sie nur ein etabliertes Muster verwenden sollten, wenn es Ihren Anforderungen entspricht. Sie können den Ansatz verwenden, den Sie gezeigt haben, wenn es für Sie funktioniert. Keine Notwendigkeit, es in ein bestimmtes Muster zu schuhen.
Um welche Art von Objekt möchten Sie sich kümmern? Möchten Sie solche Methoden in Ihrer API verwenden:
%Vor%Oder Methoden wie folgt:
%Vor%(Entschuldigung, das sind keine sehr guten Beispiele)
Wenn Sie das vorherige wollen, dann müssen alle ihre PowerSwitch
manuell dekorieren, nur um ein paar bequeme Methoden zu bekommen. Es kann für Sie jetzt bequem sein, aber ich denke, dass es für Benutzer Ihres Codes unbequem sein wird und sie sich wahrscheinlich nicht damit befassen werden. Wenn Sie Letzteres wollen, müssen Sie den Typ PowerSwitchDecorator
in Ihren Methodensignaturen verwenden, was bedeutet, dass Sie immer mit PowerSwitchDecorator
s und nicht mit root PowerSwitch
es umgehen.
Das ist eine gute Übung, wenn Sie Ihre PowerSwitch-Instanz zur Laufzeit verbessern müssen. Ich empfehle Ihnen, die PowerSwitch-Schnittstelle im Dekorateur zu implementieren. Der andere Name des Decorator-Musters ist das Proxy-Muster.
Sie können die erweiterten Methoden in einer anderen Schnittstelle definieren, die Ihre PowerSwitch-Schnittstelle erweitert. Das vermeidet eine Abhängigkeit vom Dekorator, wenn diese erweiterten Methoden aufgerufen werden müssen.
Das Erweitern einer Klasse ist eine gute Übung, wenn Sie ein Verhalten bei der Kompilierung verbessern oder neu definieren müssen.
Es ist keines der Muster.
Ein Decorator hat die Absicht, ein Objekt zu umschließen und die bereits vorhandene Funktionalität zu erweitern, wodurch die Schnittstelle für den Client transparent wird. Ein BufferedInputstream ist ein Beispiel. Beachten Sie, dass der Decorator die gleiche Schnittstelle wie den zu umwickelnden Typ implementieren sollte.
%Vor%Beachten Sie den Unterschied zum Proxy-Muster, bei dem die Hauptzielsetzung darin besteht, den Zugriff auf ein Objekt zu steuern, nicht notwendigerweise durch Umhüllen mit einem anderen Objekt. In diesem Fall würden Sie auch den Proxy die gleiche Schnittstelle implementieren lassen.
Einige Muster sehen oft ähnlich aus, der Unterschied liegt in der Absicht ihrer Verwendung. Hier ist ein allgemeinerer Thread zu diesem Thema: Wann und wie kann ein Strategie-Muster anstelle eines Dekorationsmusters angewendet werden?
Mit Ihrem Code gibt es noch keinen wirklichen Unterschied. Es sieht wie eine Strategie aus, da der PowerSwitchDecorator lediglich die Arbeit (d. H. Den Algorithmus) an einen PowerSwitch delegiert. Wenn dies Ihre Absicht ist und es alternative PowerSwitches gibt, die auf verschiedene Arten umgeschaltet werden, ist das Strategie-Pattern Ihre Wahl.
Wenn Sie stattdessen eine Reihe von PowerSwitches haben, von denen jeder das Toggeln leicht verbessert (das Toggeln schmückt) und diese PowerSwitches verschachtelt werden können, dann implementieren Sie einen Decorator. Wie bereits erwähnt, benötigen Sie in diesem Fall auch die Dekoratoren als Teil der Typhierarchie.
Ich würde sagen, es ist keines der Muster.
Dekorationsmuster
Das Decorator-Muster wird verwendet, um das Verhalten einer vorhandenen Implementierung zu erweitern. Nehmen Sie ein Grafikfenster als Beispiel, Sie möchten vielleicht ein Fenster mit Bildlaufleisten haben. Dann können Sie eine Klasse wie
haben %Vor%Das Strategie-Muster
Das Strategie-Muster wird verwendet, um verschiedene Dinge abhängig von der gewählten Strategie zu tun. Nehmen wir an, Sie machen Kaffee. Sie könnten etwas wie:
haben %Vor%und benutze es wie
%Vor%Lesen Sie die folgenden Links für weitere Informationen:
Ihre PowerSwitchDecorator
-Klasse ist kein Dekorator. Ihre Implementierung ist in der Nähe von Strategy_pattern , obwohl die Befehle Command_pattern
In Decorator
Muster, Decorator
implementiert tatsächlich die Schnittstelle (d. h. Component
) und Ihre Klasse macht das nicht gleich.
Schauen Sie sich das Klassendiagramm an
Im obigen Diagramm ist Component
eine Schnittstelle. Decorator
implementiert Component
interface und enthält die Schnittstelle mit Composition
. Sehen Sie sich die Mitgliedsvariable an - component
.
Beziehen Sie sich zum besseren Verständnis auf diese Fragen:
Tags und Links java design-patterns decorator strategy-pattern