Raumausstatter-Muster

In der objektorientierten Programmierung ist das Raumausstatter-Muster ein Designmuster, das Verhalten erlaubt, zu einem vorhandenen Gegenstand dynamisch hinzugefügt zu werden.

Einführung

Das Raumausstatter-Muster kann verwendet werden, um sich auszustrecken (schmücken) die Funktionalität eines bestimmten Gegenstands an der Durchlaufzeit unabhängig von anderen Beispielen derselben Klasse, vorausgesetzt dass ein Grundstein in der Designzeit getan wird. Das wird durch das Entwerfen einer neuen Raumausstatter-Klasse erreicht, die die ursprüngliche Klasse wickelt. Diese Verpackung konnte durch die folgende Folge von Schritten erreicht werden:

  1. Unterklasse die ursprüngliche "Decorator" Klasse in eine "Teil"-Klasse (sieh UML Diagramm);
  2. In der Raumausstatter-Klasse, fügen Sie einen Teilzeigestock als ein Feld hinzu;
  3. Passieren Sie einen Bestandteil dem Raumausstatter-Konstrukteur, um den Teilzeigestock zu initialisieren;
  4. In der Raumausstatter-Klasse, adressieren Sie alle "Teil"-Methoden zum "Teil"-Zeigestock um; und
  5. In der Klasse von ConcreteDecorator, überreiten Sie jede Bildende Methode (N), deren Verhalten modifiziert werden muss.

Dieses Muster wird entworfen, so dass vielfache Raumausstatter aufeinander aufgeschobert werden können, jedes Mal eine neue Funktionalität zur überrittenen Methode (N) hinzufügend.

Das Raumausstatter-Muster ist eine Alternative zum Subklassifizieren. Das Subklassifizieren fügt Verhalten während der Übersetzung hinzu, und die Änderung betrifft alle Beispiele der ursprünglichen Klasse; das Verzieren kann neues Verhalten an der Durchlaufzeit für individuelle Gegenstände zur Verfügung stellen.

Dieser Unterschied wird am wichtigsten, wenn es mehrere unabhängige Weisen gibt, Funktionalität zu erweitern. Auf einigen objektorientierten Programmiersprachen können Klassen nicht an der Durchlaufzeit geschaffen werden, und es ist normalerweise nicht möglich, in der Designzeit vorauszusagen, welche Kombinationen von Erweiterungen erforderlich sein werden. Das würde bedeuten, dass eine neue Klasse für jede mögliche Kombination würde gemacht werden müssen. Im Vergleich sind Raumausstatter Gegenstände, die an der Durchlaufzeit geschaffen sind, und können auf einer durchlesen Basis verbunden werden. Die Eingabe/Ausgabe-Strom-Durchführungen sowohl Javas als auch des.NET Fachwerks vereinigen das Raumausstatter-Muster.

Motivation

Als ein Beispiel, denken Sie ein Fenster in einem Fenstertechnik-System. Um zu erlauben, des Inhalts des Fensters zu scrollen, könnten wir horizontalen oder vertikalen scrollbars dazu, als passend hinzufügen mögen. Nehmen Sie an, dass Fenster durch Beispiele der Fensterklasse vertreten werden und annehmen, dass diese Klasse keine Funktionalität hat, um scrollbars hinzuzufügen. Wir konnten eine Unterklasse ScrollingWindow schaffen, der ihnen zur Verfügung stellt, oder wir ScrollingWindowDecorator schaffen konnten, der diese Funktionalität zu vorhandenen Fenstergegenständen hinzufügt. An diesem Punkt würde jede Lösung fein sein.

Wollen jetzt wir annehmen, dass wir auch die Fähigkeit wünschen, Grenzen zu unseren Fenstern hinzuzufügen. Wieder hat unsere ursprüngliche Fensterklasse keine Unterstützung. Die Unterklasse von ScrollingWindow wirft jetzt ein Problem auf, weil sie eine neue Art des Fensters effektiv geschaffen hat. Wenn wir Grenzunterstützung zu allen Fenstern hinzufügen möchten, müssen wir Unterklassen WindowWithBorder und ScrollingWindowWithBorder schaffen. Offensichtlich wird dieses Problem schlechter mit jeder neuen hinzuzufügenden Eigenschaft. Für die Raumausstatter-Lösung schaffen wir einfach einen neuen BorderedWindowDecorator-an Durchlaufzeit, wir können vorhandene Fenster mit ScrollingWindowDecorator oder BorderedWindowDecorator oder beiden schmücken, wie wir passend sehen.

Ein anderes gutes Beispiel dessen, wo ein Raumausstatter gewünscht werden kann, ist, wenn es ein Bedürfnis gibt, Zugang zu Eigenschaften eines Gegenstands oder Methoden gemäß einem Regelwerk oder vielleicht mehreren parallelen Regelwerken zu beschränken (verschiedener Benutzerausweis, usw.) In diesem Fall, anstatt die Zugriffskontrolle im ursprünglichen Gegenstand durchzuführen, wird es unverändert und unbewusst irgendwelcher Beschränkungen seines Gebrauches verlassen, und es wird in einen Zugriffskontrollraumausstatter-Gegenstand gewickelt, der dann nur der erlaubten Teilmenge der Schnittstelle des ursprünglichen Gegenstands dienen kann.

Struktur

Beispiele

Java

Das erste Beispiel (Drehbuch des Fensters/scrollen)

Das folgende javanische Beispiel illustriert den Gebrauch von Raumausstattern, die das Drehbuch des Fensters/scrollen verwenden.

//die Fensterschnittstelle

verbinden Sie Fenster {\

öffentliche leere Attraktion ;//zieht das Fenster

öffentliche Schnur getDescription ;//gibt eine Beschreibung des Fensters zurück

}\

//Durchführung eines einfachen Fensters ohne jeden scrollbars

Klasse SimpleWindow führt Fenster {\durch

öffentliche leere Attraktion {\

//ziehen Sie Fenster

}\

öffentliche Schnur getDescription {\

geben Sie "einfaches Fenster" zurück;

}\}\</Quelle>

Die folgenden Klassen enthalten die Raumausstatter für alle Klassen einschließlich der Raumausstatter-Klassen selbst.

//abstrakte Raumausstatter-Klasse - bemerkt, dass sie Fenster durchführt

abstrakte Klasse WindowDecorator führt Fenster {\durch

geschütztes Fenster decoratedWindow;//das Fenster, das wird schmückt

öffentlicher WindowDecorator (Fenster decoratedWindow) {\

this.decoratedWindow = decoratedWindow;

}\ öffentliche leere Attraktion {\

decoratedWindow.draw ;

}\}\

//der erste konkrete Raumausstatter, der vertikale scrollbar Funktionalität hinzufügt

Klasse VerticalScrollBarDecorator erweitert WindowDecorator {\

öffentlicher VerticalScrollBarDecorator (Fenster decoratedWindow) {\

fantastisch (decoratedWindow);

}\ öffentliche leere Attraktion {\ decoratedWindow.draw ;

drawVerticalScrollBar ;

}\

private Leere drawVerticalScrollBar {\

//ziehen Sie den vertikalen scrollbar

}\ öffentliche Schnur getDescription {\

geben Sie decoratedWindow.getDescription +" einschließlich vertikalen scrollbars zurück";

}\}\

//der zweite konkrete Raumausstatter, der horizontale scrollbar Funktionalität hinzufügt

Klasse HorizontalScrollBarDecorator erweitert WindowDecorator {\

öffentlicher HorizontalScrollBarDecorator (Fenster decoratedWindow) {\

fantastisch (decoratedWindow); }\ öffentliche leere Attraktion {\ decoratedWindow.draw ;

drawHorizontalScrollBar ;

}\

private Leere drawHorizontalScrollBar {\

//ziehen Sie den horizontalen scrollbar

}\ öffentliche Schnur getDescription {\

geben Sie decoratedWindow.getDescription +" einschließlich horizontalen scrollbars zurück";

}\}\</Quelle>

Hier ist ein Testprogramm, das ein Beispiel schafft, das (d. h., mit vertikalem und horizontalem scrollbars) völlig geschmückt wird, und seine Beschreibung druckt:

öffentliche Klasse DecoratedWindowTest {\

öffentliche statische leere Hauptsache (Schnur [] args) {\

//schaffen Sie ein geschmücktes Fenster mit horizontalem und vertikalem scrollbars

Fenster decoratedWindow = neuer HorizontalScrollBarDecorator (

neuer VerticalScrollBarDecorator (neuer SimpleWindow ));

//drucken Sie die Beschreibung des Fensters

System.out.println (decoratedWindow.getDescription );

}\}\</Quelle>

Die Produktion dieses Programms ist "einfaches Fenster, einschließlich vertikalen scrollbars, einschließlich horizontalen scrollbars". Bemerken Sie, wie die Methode der zwei Raumausstatter zuerst das geschmückte 's Beschreibung wiederbekommt und es mit einer Nachsilbe schmückt.

Das zweite Beispiel (Kaffee-Bilden-Drehbuch)

Das folgende javanische Beispiel illustriert den Gebrauch von Raumausstattern, die Kaffee-Bilden-Drehbuch verwenden.

In diesem Beispiel schließt das Drehbuch nur Kosten und Zutaten ein.

//Die Kaffee-Schnittstelle definiert die Funktionalität von Kaffee, der vom Raumausstatter durchgeführt ist

öffentlicher Schnittstelle-Kaffee {\

Publikum verdoppelt getCost ;//gibt die Kosten des Kaffees zurück

öffentliche Schnur getIngredients ;//gibt die Zutaten des Kaffees zurück

}\

//Durchführung eines einfachen Kaffees ohne irgendwelche Extrazutaten

öffentliche Klasse SimpleCoffee führt Kaffee {\durch

Publikum verdoppelt getCost {\

kehren Sie 1 zurück;

}\

öffentliche Schnur getIngredients {\

geben Sie "Kaffee" zurück;

}\}\</Quelle>

Die folgenden Klassen enthalten die Raumausstatter für alle Klassen einschließlich der Raumausstatter-Klassen selbst..

//abstrakte Raumausstatter-Klasse - bemerkt, dass sie Kaffee-Schnittstelle durchführt

abstrakte öffentliche Klasse CoffeeDecorator führt Kaffee {\durch

geschützter Endkaffee decoratedCoffee;

geschützte Schnur ingredientSeparator =", ";

öffentlicher CoffeeDecorator (Kaffee decoratedCoffee) {\

this.decoratedCoffee = decoratedCoffee;

}\

Publikum verdoppelt getCost {//das Einführen von Methoden der Schnittstelle

geben Sie decoratedCoffee.getCost zurück;

}\ öffentliche Schnur getIngredients {\

geben Sie decoratedCoffee.getIngredients zurück;

}\}\

//Raumausstatter-Milch, die Milch mit Kaffee mischt

//bemerken Sie, dass es CoffeeDecorator erweitert

öffentliche Klassenmilch erweitert CoffeeDecorator {\

öffentliche Milch (Kaffee decoratedCoffee) {\

fantastisch (decoratedCoffee);

}\

Publikum verdoppelt getCost {//überwiegende Methoden, die in der abstrakten Superklasse definiert sind

geben Sie super.getCost + 0.5 zurück;

}\ öffentliche Schnur getIngredients {\

geben Sie super.getIngredients + ingredientSeparator + "Milch" zurück;

}\}\

//Raumausstatter-Peitsche, die Peitsche mit Kaffee mischt

//bemerken Sie, dass es CoffeeDecorator erweitert

öffentliche Klassenpeitsche erweitert CoffeeDecorator {\

öffentliche Peitsche (Kaffee decoratedCoffee) {\

fantastisch (decoratedCoffee); }\ Publikum verdoppelt getCost {\

geben Sie super.getCost + 0.7 zurück;

}\ öffentliche Schnur getIngredients {\

geben Sie super.getIngredients + ingredientSeparator + "Peitsche" zurück;

}\}\

//Raumausstatter-Nieselregen, der Nieselregen mit Kaffee mischt

//bemerken Sie, dass es CoffeeDecorator erweitert

öffentlicher Klassennieselregen erweitert CoffeeDecorator {\

öffentlicher Nieselregen (Kaffee decoratedCoffee) {\

fantastisch (decoratedCoffee); }\ Publikum verdoppelt getCost {\

geben Sie super.getCost + 0.2 zurück;

}\ öffentliche Schnur getIngredients {\

geben Sie super.getIngredients + ingredientSeparator + "Nieselregen" zurück;

}\}\</Quelle>

Hier ist ein Testprogramm, das ein Beispiel schafft, das (d. h., mit Milch, Peitsche, Nieselregen) völlig geschmückt wird, und berechnen Sie Kosten von Kaffee und seine Zutaten druckt:

öffentliche Klasse Wichtiger

{\

öffentliche statische leere Hauptsache (Schnur [] args)

{\

Kaffee c = neuer SimpleCoffee ;

System.out.println ("Kosten: "+ c.getCost +"; Zutaten:" + c.getIngredients );

c = neue Milch (c);

System.out.println ("Kosten: "+ c.getCost +"; Zutaten:" + c.getIngredients );

c = neuer Nieselregen (c);

System.out.println ("Kosten: "+ c.getCost +"; Zutaten:" + c.getIngredients );

c = neue Peitsche (c);

System.out.println ("Kosten: "+ c.getCost +"; Zutaten:" + c.getIngredients );

//Bemerken Sie, dass Sie auch mehr als einen Raumausstatter desselben Typs aufschobern können

c = neuer Nieselregen (c); System.out.println ("Kosten: "+ c.getCost +"; Zutaten:" + c.getIngredients ); }\}\</Quelle>

Die Produktion dieses Programms wird unten gegeben:

Kosten: 1.0; Zutaten: Kaffee

Kosten: 1.5; Zutaten: Kaffee, Milch

Kosten: 1.7; Zutaten: Kaffee, Milch, Nieselregen

Kosten: 2.4; Zutaten: Kaffee, Milch, Nieselregen, Peitsche

Kosten: 2.6; Zutaten: Kaffee, Milch, Nieselregen, Peitsche, Nieselregen

</Code>

Dynamische Sprachen

Das Raumausstatter-Muster kann auch auf dynamischen Sprachen weder mit Schnittstellen noch mit traditionellem OOP Erbe durchgeführt werden.

JavaScript (Kaffee-Bilden-Drehbuch)

//Klasse, die zu schmücken

ist

fungieren Sie Kaffee {\

}\

Coffee.prototype.cost = Funktion {\

kehren Sie 1 zurück;

};

//Raumausstatter ein

fungieren Sie Milch (Kaffee) {\

var currentCost = coffee.cost ;

coffee.cost = Funktion {\

geben Sie currentCost + 0.5 zurück;

};

geben Sie Kaffee zurück;

}\

//Raumausstatter B

fungieren Sie Peitsche (Kaffee) {\

var currentCost = coffee.cost ; coffee.cost = Funktion {\

geben Sie currentCost + 0.7 zurück;

}; geben Sie Kaffee zurück;}\

//Raumausstatter C

fungieren Sie Nieselregen (Kaffee) {\

var currentCost = coffee.cost ; coffee.cost = Funktion {\

geben Sie currentCost + 0.2 zurück;

}; geben Sie Kaffee zurück;}\

//Hier ist eine Weise, es zu verwenden

Var-Kaffee = neue Milch (neue Peitsche (neuer Nieselregen (neuer Kaffee )));

Alarmsignal (coffee.cost );

//Hier ist ein anderer

Var-Kaffee = neuer Kaffee ;

Kaffee = neuer Nieselregen (Kaffee);

Kaffee = neue Peitsche (Kaffee);

Kaffee = neue Milch (Kaffee);

Alarmsignal (coffee.cost );

</Quelle>

Siehe auch

Links


Zerlegbares Muster / Proxymuster
Impressum & Datenschutz