Neulich hörte ich die Sendung Car Talk des National Public Radio, eine beliebte wöchentliche Sendung, in der Anrufer Fragen zu ihren Fahrzeugen stellen. Vor jeder Sendepause bitten die Moderatoren die Anrufer, die Nummer 1-800-CAR-TALK zu wählen, die der Nummer 1-800-227-8255 entspricht. Erstere ist natürlich viel leichter zu merken als letztere, was zum Teil daran liegt, dass die Worte „CAR TALK“ ein Kompositum sind: zwei Wörter, die für sieben Ziffern stehen. Menschen finden es im Allgemeinen einfacher, mit Komposita umzugehen, als mit ihren einzelnen Bestandteilen. Auch bei der Entwicklung objektorientierter Software ist es oft bequemer, Komposita genauso zu manipulieren wie einzelne Komponenten. Diese Prämisse stellt das Grundprinzip des Composite Design Patterns dar, dem Thema dieser Java Design Patterns-Folge.
- Das Composite Pattern
- Das Composite-Muster und Struts Tiles
- Komplexe Layouts von Hand implementieren
- Beispiel 1. Ein komplexes Layout von Hand implementiert
- Komplexe Layouts mit JSP-Includes implementieren
- Beispiel 2. Ein komplexes Layout, das mit JSP implementiert wurde, enthält
- Beispiel 3. sidebar.jsp
- Beispiel 4. header.jsp
- Beispiel 5. content.jsp
- Beispiel 6. footer.jsp
- Komplexe Layouts mit Struts Tiles implementieren
- Beispiel 7. Verwenden Sie Struts Tiles, um das Layout zu kapseln
- Beispiel 8. WEB-INF/tiles-defs.xml
- Beispiel 9. header-footer-sidebar-layout.jsp
- Verwenden Sie das Composite-Muster mit Struts Tiles
- Beispiel 10. WEB-INF/tiles-defs.xml: Verwenden Sie das Composite-Muster
- Beispiel 11. sidebar-layout.jsp
- Beispiel 12. flags.jsp
- Beispiel 13. sidebar-links.jsp
- Heutzutage sind alle Composites
- Hausaufgaben
- Hausaufgabe vom letzten Mal
- Beispiel H1. flags.jsp
- Beispiel H2. WEB-INF/web.xml (Auszug)
- Beispiel H3. WEB-INF/struts-config.xml
- Beispiel H4. WEB-INF/classes/actions/FlagAction.java
- Beispiel H5. WEB-INF/web.xml (Auszug)
- Beispiel H6. sidebar-links.jsp
- Beispiel H7. header.jsp
- Beispiel H8. content.jsp
- Beispiel H9. footer.jsp
- Beispiel H10. WEB-INF/classes/resources_en.properties
- Beispiel H11. WEB-INF/classes/resources_zh.properties
- Erfahren Sie mehr über dieses Thema
Das Composite Pattern
Bevor wir uns mit dem Composite Pattern beschäftigen, muss ich zunächst Composite-Objekte definieren: Objekte, die andere Objekte enthalten; zum Beispiel kann eine Zeichnung aus grafischen Primitiven wie Linien, Kreisen, Rechtecken, Text usw. bestehen.
Java-Entwickler brauchen das Composite-Muster, weil wir Composites oft auf die gleiche Weise manipulieren müssen wie primitive Objekte. Zum Beispiel müssen grafische Primitive wie Linien oder Text gezeichnet, verschoben und in der Größe verändert werden. Aber wir möchten die gleichen Operationen auch an Composites, wie z. B. Zeichnungen, durchführen, die aus diesen Primitiven bestehen. Im Idealfall möchten wir Operationen an primitiven Objekten und Komposita auf genau dieselbe Weise durchführen, ohne zwischen den beiden zu unterscheiden. Wenn wir zwischen primitiven Objekten und Composites unterscheiden müssen, um dieselben Operationen mit diesen beiden Objekttypen durchzuführen, würde unser Code komplexer und schwieriger zu implementieren, zu warten und zu erweitern sein.
In Design Patterns beschreiben die Autoren das Composite-Muster wie folgt:
Zusammengesetzte Objekte in Baumstrukturen, um Teil-Ganzes-Hierarchien darzustellen. Mit Composite können Clients einzelne Objekte und Kompositionen von Objekten einheitlich behandeln.
Die Implementierung des Composite-Musters ist einfach. Composite-Klassen erweitern eine Basisklasse, die primitive Objekte repräsentiert. Abbildung 1 zeigt ein Klassendiagramm, das die Struktur des Composite-Musters veranschaulicht.
Im Klassendiagramm von Abbildung 1 habe ich Klassennamen aus der Diskussion über das Composite-Muster von Design Pattern verwendet: Component
steht für eine Basisklasse (oder möglicherweise eine Schnittstelle) für primitive Objekte, und Composite
steht für eine zusammengesetzte Klasse. Beispielsweise könnte die Klasse Component
eine Basisklasse für grafische Primitive darstellen, während die Klasse Composite
eine Drawing
-Klasse darstellen könnte. Die Klasse Leaf
in Abbildung 1 steht für ein konkretes primitives Objekt, zum Beispiel eine Line
-Klasse oder eine Text
-Klasse. Die Methoden Operation1()
und Operation2()
stellen domänenspezifische Methoden dar, die von den Klassen Component
und Composite
implementiert werden.
Die Klasse Composite
verwaltet eine Sammlung von Komponenten. Normalerweise werden Composite
-Methoden implementiert, indem über diese Sammlung iteriert wird und die entsprechende Methode für jede Component
in der Sammlung aufgerufen wird. Zum Beispiel könnte eine Drawing
-Klasse ihre draw()
-Methode wie folgt implementieren:
Für jede Methode, die in der Component
-Klasse implementiert ist, implementiert die Composite
-Klasse eine Methode mit der gleichen Signatur, die über die Komponenten des Composites iteriert, wie die oben aufgeführte draw()
-Methode zeigt.
Die Klasse Composite
erweitert die Klasse Component
, so dass Sie einer Methode, die eine Komponente erwartet, ein Kompositum übergeben können; betrachten Sie zum Beispiel die folgende Methode:
// This method is implemented in a class that's unrelated to the// Component and Composite classespublic void repaint(Component component) { // The component can be a composite, but since it extends // the Component class, this method need not // distinguish between components and composites component.draw();}
Der vorhergehenden Methode wird eine Komponente übergeben – entweder eine einfache Komponente oder ein Kompositum – und ruft dann die Methode draw()
dieser Komponente auf. Da die Klasse Composite
die Klasse Component
erweitert, muss die Methode repaint()
nicht zwischen Komponenten und Composites unterscheiden – sie ruft einfach die Methode draw()
für die Komponente (oder das Composite) auf.
Das Klassendiagramm des Composite-Musters in Abbildung 1 verdeutlicht ein Problem mit dem Muster: Sie müssen zwischen Komponenten und Composites unterscheiden, wenn Sie eine Component
referenzieren, und Sie müssen eine Composite-spezifische Methode aufrufen, wie addComponent()
. In der Regel erfüllt man diese Anforderung, indem man der Klasse Component
eine Methode, wie isComposite()
, hinzufügt. Diese Methode gibt false
für Komponenten zurück und wird in der Klasse Composite
überschrieben, um true
zurückzugeben. Zusätzlich müssen Sie die Component
-Referenz in eine Composite
-Instanz umwandeln, etwa so:
Beachten Sie, dass der addComponent()
-Methode eine Component
-Referenz übergeben wird, die entweder eine primitive Komponente oder ein Composite sein kann. Da es sich bei dieser Komponente um eine zusammengesetzte Komponente handeln kann, können Sie die Komponenten in einer Baumstruktur zusammensetzen, wie in dem oben erwähnten Zitat aus Design Patterns angegeben.
Abbildung 2 zeigt eine alternative Implementierung des Composite-Musters.
Wenn Sie das Composite-Muster aus Abbildung 2 implementieren, müssen Sie nie zwischen Komponenten und Composites unterscheiden, und Sie müssen eine Component
-Referenz nicht auf eine Composite
-Instanz casten. Das oben aufgeführte Codefragment reduziert sich also auf eine einzige Zeile:
...component.addComponent(someComponentThatCouldBeAComposite);...
Aber wenn der Component
-Verweis im vorangegangenen Codefragment nicht auf eine Composite
-Instanz verweist, was soll dann die addComponent()
tun? Dies ist ein wesentlicher Streitpunkt bei der Implementierung des Composite-Musters in Abbildung 2. Da primitive Komponenten keine anderen Komponenten enthalten, macht das Hinzufügen einer Komponente zu einer anderen Komponente keinen Sinn, so dass die Methode Component.addComponent()
entweder stillschweigend fehlschlagen oder eine Ausnahme auslösen kann. Normalerweise wird das Hinzufügen einer Komponente zu einer anderen primitiven Komponente als Fehler angesehen, so dass das Auslösen einer Ausnahme vielleicht die beste Vorgehensweise ist.
Welche Implementierung des Composite-Musters – die in Abbildung 1 oder die in Abbildung 2 – funktioniert also am besten? Design Patterns bevorzugt die Implementierung in Abbildung 2, weil man nie zwischen Komponenten und Containern unterscheiden muss und weil man nie einen Cast durchführen muss. Ich persönlich bevorzuge die Implementierung von Abbildung 1, da ich eine starke Abneigung gegen die Implementierung von Methoden in einer Klasse habe, die für diesen Objekttyp nicht sinnvoll sind.
Nachdem Sie nun das Composite-Muster und seine Implementierung verstanden haben, lassen Sie uns ein Beispiel für das Composite-Muster mit dem Apache Struts JavaServer Pages (JSP) Framework untersuchen.
Das Composite-Muster und Struts Tiles
Das Apache Struts-Framework enthält eine JSP-Tag-Bibliothek, bekannt als Tiles, mit der Sie eine Webseite aus mehreren JSPs zusammenstellen können. Tiles ist eigentlich eine Implementierung des J2EE (Java 2 Platform, Enterprise Edition) CompositeView-Musters, das wiederum auf dem Design Patterns Composite-Muster basiert. Bevor wir die Relevanz des Composite-Musters für die Tiles-Tag-Bibliothek erörtern, wollen wir zunächst die Gründe für Tiles und seine Verwendung erläutern. Wenn Sie bereits mit Struts Tiles vertraut sind, können Sie die folgenden Abschnitte überspringen und bei „Use the Composite Pattern with Struts Tiles“ (Verwendung des Composite-Musters mit Struts Tiles) beginnen.
Hinweis: Sie können mehr über das J2EE CompositeView-Muster in meinem Artikel „Web Application Components Made Easy with Composite View“ (JavaWorld, Dezember 2001) lesen.
Designer konstruieren Webseiten oft mit einer Reihe von diskreten Bereichen; die Webseite in Abbildung 3 besteht beispielsweise aus einer Seitenleiste, einer Kopfzeile, einem Inhaltsbereich und einer Fußzeile.
Websites enthalten oft mehrere Webseiten mit identischen Layouts, wie das Layout von Seitenleiste/Kopfzeile/Inhaltsbereich/Fußzeile in Abbildung 3. Mit Struts Tiles können Sie sowohl Inhalt als auch Layout auf mehreren Webseiten wiederverwenden. Bevor wir diese Wiederverwendung besprechen, sehen wir uns an, wie das Layout von Abbildung 3 traditionell mit HTML allein implementiert wird.
Komplexe Layouts von Hand implementieren
Beispiel 1 zeigt, wie Sie die Webseite von Abbildung 3 mit HTML implementieren können:
Beispiel 1. Ein komplexes Layout von Hand implementiert
Das vorangegangene JSP hat zwei große Nachteile: Erstens ist der Inhalt der Seite in die JSP eingebettet, so dass Sie nichts davon wiederverwenden können, obwohl die Seitenleiste, die Kopfzeile und die Fußzeile wahrscheinlich auf vielen Webseiten gleich sind. Zweitens ist auch das Layout der Seite in diese JSP eingebettet, so dass Sie es ebenfalls nicht wiederverwenden können, auch wenn viele andere Webseiten derselben Website dasselbe Layout verwenden. Mit der <jsp:include>
-Aktion lässt sich der erste Nachteil beheben, wie ich im Folgenden erläutere.
Komplexe Layouts mit JSP-Includes implementieren
Beispiel 2 zeigt eine Implementierung der Webseite in Abbildung 3, die <jsp:include>
verwendet:
Beispiel 2. Ein komplexes Layout, das mit JSP implementiert wurde, enthält
Die vorangehende JSP enthält den Inhalt anderer JSPs mit <jsp:include>
. Da ich diesen Inhalt in separaten JSPs gekapselt habe, können Sie ihn für andere Webseiten wiederverwenden:
Der Vollständigkeit halber habe ich unten die JSPs aufgelistet, die von der vorhergehenden JSP eingeschlossen werden:
Beispiel 4. header.jsp
<font size='6'>Welcome to Sabreware, Inc.</font><hr>
Beispiel 5. content.jsp
<font size='4'>Page-specific content goes here</font>
<hr>Thanks for stopping by!
Auch wenn die JSP von Beispiel 2 <jsp:include>
verwendet, um Inhalte wiederzuverwenden, kann man das Layout der Seite nicht wiederverwenden, da es in dieser JSP fest kodiert ist. Mit Struts Tiles können Sie sowohl den Inhalt als auch das Layout wiederverwenden, wie im nächsten Abschnitt gezeigt wird.
Komplexe Layouts mit Struts Tiles implementieren
Beispiel 7 zeigt die Webseite in Abbildung 3, die mit Struts Tiles implementiert wurde:
Beispiel 7. Verwenden Sie Struts Tiles, um das Layout zu kapseln
Die vorangehende JSP verwendet das <tiles:insert>
-Tag, um die JSP von Abbildung 3 zu erstellen. Diese JSP wird durch eine Kacheldefinition namens sidebar-header-footer-definition
definiert. Diese Definition befindet sich in der Tiles-Konfigurationsdatei, die in diesem Fall WEB-INF/tiles-defs.xml
heißt und in Beispiel 8 aufgeführt ist:
Beispiel 8. WEB-INF/tiles-defs.xml
Die vorangehende Tiles-Definition spezifiziert das Seitenlayout, gekapselt in header-footer-sidebar-layout.jsp
, und den Inhalt der Seite, gekapselt in sidebar.jsp
, header.jsp
, content.jsp
und footer.jsp
, wie in den Beispielen 3-6 aufgeführt. Beispiel 9 listet die JSP auf, die das Layout definiert: header-footer-sidebar-layout.jsp
:
Die vorangehende JSP kapselt das Layout und fügt den Inhalt entsprechend den Werten ein, die für die Regionen Sidebar, Editor, Content und Footer in der Tiles-Definitionsdatei angegeben sind, was die Wiederverwendung sowohl des Inhalts als auch des Layouts erleichtert. Sie könnten beispielsweise eine weitere Tiles-Definition mit demselben Layout, derselben Seitenleiste, demselben Editor und derselben Fußzeile, aber anderem Inhalt definieren:
Um die durch die Tiles-Definition a-different-sidebar-header-footer-definition
definierte JSP zu erstellen, verwenden Sie den <tiles:insert>
-Tag wie folgt:
Dank Struts Tiles können Sie sowohl Inhalt als auch Layout wiederverwenden, was sich für Websites mit vielen JSPs, die Layout und einige Inhalte gemeinsam nutzen, als unschätzbar erweist. Wenn Sie sich jedoch den Code aus den Beispielen 7-9 genau ansehen, werden Sie feststellen, dass das Layout für die Sidebar-Region in sidebar.jsp
, das in Beispiel 3 aufgeführt ist, fest kodiert ist. Das bedeutet, dass Sie dieses Layout nicht wiederverwenden können. Glücklicherweise implementiert die Tiles-Tag-Bibliothek das Composite-Muster, mit dem wir eine Tiles-Definition – anstelle einer JSP – für eine Region angeben können. Im nächsten Abschnitt erkläre ich, wie man diese Composite-Muster-Implementierung verwendet.
Verwenden Sie das Composite-Muster mit Struts Tiles
Struts Tiles implementiert das Composite-Muster, wobei die Klasse Component
durch JSPs und die Klasse Composite
durch eine Tiles-Definition dargestellt wird. Mit dieser Implementierung können Sie entweder eine JSP (eine Komponente) oder eine Tiles-Definition (ein Composite) als Inhalt für eine JSP-Region angeben. Beispiel 10 veranschaulicht diese Funktion:
Beispiel 10. WEB-INF/tiles-defs.xml: Verwenden Sie das Composite-Muster
Die vorangehende Tiles-Konfigurationsdatei definiert zwei Tiles-Definitionen: sidebar-definition
und sidebar-header-footer-definition
. sidebar-definition
wird als Wert für den Seitenleistenbereich in sidebar-header-footer-definition
angegeben. Sie können es als solches angeben, weil Tiles das Composite-Muster implementiert, indem Tiles eine Definition (eine Composite
, die eine JSP-Sammlung ist) angibt, wo Sie normalerweise eine einzelne JSP (die eine Component
ist) angeben würden.
Das Layout der Seitenleiste ist in der sidebar-layout.jsp
von Beispiel 11 gekapselt:
Beispiel 12 führt flags.jsp
auf, das als Inhalt für den top
-Bereich der Seitenleiste angegeben ist, und Beispiel 13 führt sidebar-links.jsp
auf, das als bottom
-Bereich der Seitenleiste angegeben ist:
Beispiel 12. flags.jsp
Jetzt kann die sidebar-definition
andere Regionen mit einer oberen und unteren Komponente definieren, obwohl Sie diese Definition wahrscheinlich in etwas allgemeineres wie top-bottom-definition
umbenennen sollten.
Heutzutage sind alle Composites
Das Composite-Muster ist bei Präsentations-Frameworks wie Swing und Struts sehr beliebt, da es die Verschachtelung von Containern ermöglicht, indem Komponenten und ihre Container genau gleich behandelt werden. Struts Tiles verwendet das Composite-Muster, um eine einfache JSP oder eine Tiles-Definition – eine Sammlung von JSPs – als Inhalt einer Kachel anzugeben. Das ist eine mächtige Fähigkeit, die die Verwaltung großer Websites mit unterschiedlichen Layouts erleichtert.
Der folgende Abschnitt „Hausaufgaben vom letzten Mal“ erweitert die Diskussion dieses Artikels, indem er die vorhergehende Anwendung mit einer Struts-Aktion und der JSP Standard Tag Library (JSTL) internationalisiert.
Hausaufgaben
Diskutieren Sie, wie Swing das Composite-Muster mit den Klassen Component
und Container
implementiert.
Hausaufgabe vom letzten Mal
In der letzten Aufgabe wurden Sie gebeten, Struts von http://jakarta.apache.org/struts/index.html herunterzuladen und Ihre eigene Struts-Action-Klasse zu implementieren.
Für diese Aufgabe habe ich mich entschieden, eine Struts-Action in Verbindung mit der JSP Standard Tag Library (JSTL) zu implementieren, um die Webanwendung von Beispiel 1 zu internationalisieren. Obwohl Struts die notwendige Infrastruktur für die Internationalisierung Ihrer Webanwendungen bietet, sollten Sie JSTL für diese Aufgabe verwenden, da JSTL ein Standard ist. Irgendwann werden die Internationalisierungsfunktionen von Struts wahrscheinlich veraltet sein oder in JSTL integriert werden.
Nachdem ich die Webanwendung von Beispiel 1 mit einer Struts-Aktion und JSTL internationalisiert habe, habe ich diese Anwendung für Chinesisch lokalisiert. Abbildung H1 zeigt das Ergebnis.
Anmerkung: Ich kenne kein einziges Wort Chinesisch, geschweige denn, wie man die Sprache schreibt, daher ist das Chinesisch in Abbildung H1 aus willkürlichen Unicode-Zeichenfolgen zusammengesetzt. Aber es sieht trotzdem cool aus.
Beachten Sie, dass ich die href
-Attribute im flags.jsp
von Beispiel 12 als leere Strings angegeben habe, so dass der Servlet-Container die aktuelle JSP neu lädt, wenn Sie auf die Flaggen klicken. Daher besteht der erste Schritt zur Internationalisierung der Webanwendung darin, eine URL für diese Attribute anzugeben, wie in Beispiel H1:
Beispiel H1. flags.jsp
Die URL für jedes href
-Attribut ist die gleiche: flags.do
. An diese URL werden zwei Anforderungsparameter angehängt: einer für das Gebietsschema, das dem Flag entspricht, und ein weiterer, der den Pfad der aktuellen JSP darstellt. Den letzteren Anforderungsparameter erhalten Sie durch den Aufruf der Http.ServletRequest.getServletPath()
-Methode.
Im Deployment Descriptor der Anwendung habe ich alle URLs, die auf .do
enden, dem Struts-Action-Servlet zugeordnet, etwa so:
Beispiel H2. WEB-INF/web.xml (Auszug)
Hinweis: Weitere Informationen über Struts und das Struts-Action-Servlet finden Sie in meinem Artikel „Take Command of Your Software“ (JavaWorld, Juni 2002).
Als Nächstes habe ich den Pfad /flags
auf die Struts-Action actions.FlagAction
in der Struts-Konfigurationsdatei abgebildet, die in Beispiel H3 aufgeführt ist:
Beispiel H3. WEB-INF/struts-config.xml
Aufgrund dieser Zuordnung bewirkt die URL flags.do
, dass das Struts-Action-Servlet die Methode actions.FlagAction.execute()
aufruft; daher wird beim Klicken auf eine Flagge die Methode actions.FlagAction.execute()
aufgerufen. Beispiel H4 listet die Klasse actions.FlagAction
auf:
Beispiel H4. WEB-INF/classes/actions/FlagAction.java
Die actions.FlagAction.execute()
-Methode erhält eine Referenz auf den locale
-Anforderungsparameter und übergibt diesen Wert an die set()
-Methode der JSTL Config
-Klasse. Diese Methode speichert die Zeichenkette, die das Gebietsschema repräsentiert, in der FMT_LOCALE
Konfigurationseinstellung, die JSTL zur Lokalisierung von Text und zur Formatierung von Zahlen, Währungen, Prozenten und Datumsangaben verwendet.
Nachdem ich nun ein Gebietsschema für JSTL-Internationalisierungsaktionen angegeben habe, gebe ich als Nächstes ein Ressourcenbündel im Bereitstellungsdeskriptor der Anwendung an, von dem ein Auszug in Beispiel H5 aufgeführt ist:
Beispiel H5. WEB-INF/web.xml (Auszug)
Der Basisname des Ressourcenbündels resources
ist für den Parameter javax.servlet.jsp.jstl.fmt.localizationContext
zur Kontextinitialisierung angegeben. Das bedeutet, dass JSTL nach einer Datei mit dem Namen resources_en.properties
sucht, wenn das Gebietsschema auf britisches Englisch (en-GB
) eingestellt ist, und nach resources_zh.properties
, wenn das Gebietsschema auf Chinesisch (zh-ZH
) eingestellt ist.
Nachdem ich nun ein Ressourcenbündel und ein Gebietsschema für die JSTL-Internationalisierungsaktionen angegeben habe, ändere ich als Nächstes die JSP-Dateien, um diese Aktionen zu verwenden, wie die Beispiele H6-H9 zeigen:
Beispiel H7. header.jsp
Beispiel H8. content.jsp
Die JSPs der Beispiele H6-H9 verwenden die JSTL-Aktion <fmt:message>
zum Extrahieren von Unicode-Zeichenfolgen aus dem im Bereitstellungsdeskriptor angegebenen Ressourcenbündel. Die Beispiele H10 und H11 listen die Ressourcenbündel für Englisch bzw. Chinesisch auf:
Beispiel H10. WEB-INF/classes/resources_en.properties
Beispiel H11. WEB-INF/classes/resources_zh.properties
In einer E-Mail an mich schrieb Joseph Friedman:
In „Decorate Your Java Code“ (JavaWorld, Dezember 2001) schreiben Sie:
„Das umschließende Objekt – bekannt als Dekorator – entspricht der Schnittstelle des Objekts, das es umschließt, so dass der Dekorator verwendet werden kann, als wäre er eine Instanz des Objekts, das er umschließt.“
Das Codebeispiel dekoriert jedoch
FileReader
mit einemLineNumberReader
und ruftreadLine()
auf, das nicht in derFileReader
-Schnittstelle enthalten ist; daher verwenden SieLineNumberReader
nicht transparent.
Beide, FileReader
und LineNumberReader
, entsprechen der Schnittstelle, die durch die Klasse Reader
definiert ist, die sie beide erweitern. Die Idee ist, dass man den Dekorator an jede Methode übergeben kann, die einen Verweis auf eine Reader
erwartet. Diese Methoden wissen nichts von den besonderen Fähigkeiten des Dekorators – in diesem Fall die Fähigkeit, Dateien zu lesen und Zeilennummern zu erzeugen.
Die Tatsache, dass der Dekorator (eine oder mehrere) Methoden besitzt, die dem dekorierten Objekt fehlen, verstößt in keiner Weise gegen die Absicht des Decorator-Musters; in der Tat ist das das zentrale Merkmal dieses Musters: Funktionalität zur Laufzeit zu einem Objekt hinzuzufügen, indem Objekte rekursiv dekoriert werden.
Wenn Sie sich Design Patterns Seite 173 ansehen, werden Sie folgendes sehen:
Decorator Unterklassen können Operationen für spezifische Funktionalität hinzufügen. Die
ScrollTo
-Operation vonScrollDecorator
ermöglicht es beispielsweise anderen Objekten, die Schnittstelle zu scrollen, *wenn* sie wissen, dass sich einScrollDecorator
-Objekt in der Schnittstelle befindet.
David Geary ist der Autor von Core JSTL Mastering the JSP Standard TagLibrary, das diesen Herbst von Prentice-Hall und Sun Microsystems Press veröffentlicht wird; Advanced JavaServer Pages (PrenticeHall, 2001; ISBN: 0130307041) und der Graphic Java-Serie (Sun Microsystems Press). David entwickelt seit 18 Jahren objektorientierte Software mit einer Vielzahl von objektorientierten Sprachen. Seit der Veröffentlichung des GOF-Design Patterns Buches im Jahr 1994 ist David ein aktiver Verfechter von Design Patterns und hat Design Patterns in Smalltalk, C++ und Java verwendet und implementiert. Seit 1997 arbeitet David Vollzeit als Autor und gelegentlicher Redner und Berater. David ist Mitglied der Expertengruppen, die die benutzerdefinierte JSP-Standard-Tag-Bibliothek und JavaServer Faces definieren, und er trägt zum Apache Struts JSP-Framework bei.