Das JDK-1.1 unterscheidet zwischen Strömen für
Weiterhin werden die Ströme nach der Art der Datenquellen/-senken unterschieden:
![]()
Beispielprogramm zum Kopieren einer Datei.
Angewendetes Entwurfsmuster
Das Entwurfsmuster Dekorierer (durchsichtige Hülle, Wrapper) ist von den Entwicklern des java.io Paketes angewendet worden. Es lautet in Kurzform:"Erweitere ein Objekt dynamisch um Zuständigkeiten. Dekorierer bieten eine flexible Alternative zur Unterklassenbildung, um die Funktionalität einer Klasse zu erweitern."Das Muster unterscheidet zwischen konkreten und dekorierenden Objekten. Eine konkretes Objekt stellt eine unverzichtbare Basisoperation bereit, im Beispiel hier ist das ein Strom, der eine Schreib- oder Leseoperation durch direkten Zugriff auf die Datenquellen/-senken realisiert und damit zu einer der folgenden Klassen gehört: FileInputStream, FileOutputStream, FileReader, FileWriter, StringReader, StringWriter, CharArrayReader, CharArrayWriter, ByteArrayInputStream, ByteArrayOutputStream, PipedInputStream, PipedOutputStream, PipedReader, PipedWriter.
Ein dekorierendes Objekt ergänzt ein anderes Objekt um eine bestimmte zusätzliche Operation oder einen weiteren Zustand. Dabei spielt es keine Rolle, ob das so dekorierte (umhüllte) Objekt konkret oder gar selbst dekorierend (umhüllend) ist. Im Beipiel gehört ein dekorierendes (umhüllendes) Objekt zu einer der Klassen: BufferedReader, BufferedWriter, BufferedInputStream, BufferedOutputStream, FilterReader, FilterInputStream, FilterWriter, FilterOutputStream, InputStreamReader, OutputStreamWriter, ObjectInputStream, ObjectOutputStream, DataInputStream, DataOutputStream, SequenceInputStream, LineNumberReader, PushbackReader, PushbackInputStream, PrintWriter. Ein dekorierendes Objekt stellt die Basisoperation ebenfalls bereit, realisiert diese Operation aber nicht selbst, sondern beauftragt im allgemeinen das umhüllte Objekt mit der Erledigung dieser Operation, z.B. wird die Anforderung an einen PushbackReader, eine einfache Leseoperation auszuführen, an das umhüllte Objekt delegiert, das z.B. ein FileReader Objekt sein kann.Durch das Dekorierer werden die einzelnen Verarbeitungsströme flexibel miteinander kombinierbar und zwar in einer Vielzahl von Möglichkeiten. Es wird vermieden, für jede dieser Möglichkeiten eine eigene Klasse zu definieren. Z.B in einem Parser wird meist ein Eingabestrom benötigt, der sowohl Zeilen zählen als auch ein Zeichen vorausschauen kann und die Zeichen aus einer Datei liest. Statt nun eine Klasse PushBackLineNumberFileReader in der Klassenbibliothek vorzusehen, wird ein derartiger Strom durch sukzessives, mehrmaliges Dekorieren (Umhüllen) eines konkreten Objekts zur Laufzeit erzeugt. Im Quelltext kann das so aussehen:
FileReader fr = new FileReader("ein.txt");Innerhalb des Parsers können nun die benötigten Operationen angefordert werden:
LineNumberReader lnr = new LineNumberReader(fr);
PushbackReader pbr = new PushbackReader(fr);...Die Operationen der umhüllten Objekte stehen nach wie vor zur Verfügung, wie z.B. dieMethode getLineNumber(). Daher spricht man hier auch von einer durchsichtigen Hülle.
int n = lnr.getLineNumber();
...
int c = fr.read();
c = lnr.read();
..;
pbr.unread(c);
Das Dekorierermuster bietet eine Alternative zur Vererbung, insbesondere in solchen Fällen, in denen eine Variantenexplosion droht.