So, erst einmal 'nen neuen Kaffe und nun geht's weiter
Zitat:
Das Problem mit solchen Konstruktionen ist eben der oberste Stream, denn der muß ja von einer ReadOnly Stream-Kette in eine WriteOnly-Stream Kette die Daten pumpen.
Bei der Erstellung eines
InputStreams wäre zwar ein Wrapping denkbar in der Form
myStream:= WrappingInputStream(AnOutputStream);
ähnlich, wie es beim
FiFoStream geschehen ist, in diesem Fall müsste aber jeder
OutputStream intern einen Puffer vorhalten, bzw ein Puffer-Stream zwischengeschaltet werden, was ich für wenig elegant halte.
Tatsächlich liese sich doch das gepufferte Kopieren einer Datei wie folgt Realisieren:
Delphi-Quellcode:
myInStream:= BufferedInputStream(FileInputStream('InFile'), 4096);
myOutStream:= BufferedOutputStream(FileOutputStream('OutFile'), 4096);
while not myInStream.isEOF do
myOutStream.Write(myInStream.Read);
myOutStream.Flush;
myOutStream.Close;
(selbstverständlich sollte der Destruktur eines Streams selbstständig
Close bzw
Close zunächst
Flush aufrufen. Auch optionale Parameter sind bei der Erzeugung von Streams, zB bei der Wahl der Puffergröße denkbar).
Diese Schleife bildet also das Bindeglied der Ein- und Ausgabeströme und kann ihrerseits in einer Hilfsklasse implementiert werden. zB
Delphi-Quellcode:
myConsigner:= StreamConsigner(AnInputStream, AnOutputStream);
while myConsigner.HasData do
begin
myConsigner.ConsignData;
Log('Transfered Bytes: %d', [myConsigner.DataCount]);
end;
das Flushen und Schließend der Outputstreams kann dieser Zusteller ebenfalls selbstständig übernehmen, da ihm durch den Eingabestrom bekannt sein sollte, wann keine weiteren Daten vorliegen...
Zitat:
Wichtig ist meiner Meinung nach das nicht jede Interface Klasse ALLE möglichen Operationen veröffentlich, sondern eher über Typcast's andere Interface Klassen unterstützt.
Das sehe ebenfalls als notwendig an, um eine möglichst lose Kopplung zu erreichen. Die Vererbung von Interfaces halte ich auch für eine sinnvolle Variante, obwohl die Signaturen so mitunter zu sog. God-Facades mutieren können...
Denkbar wäre noch der Einsatz von Interfaces für jede konkrete Klasse zur Abbildung deren speziellen Fähigkeiten, falls diese Funktionen doch einmal innerhalb eines Clients, im Wissen um diese Schnittstelle, benötgtigt werden sollten.
Zu bedenken bleibt, dass bei der Kaskadierung (wrapping) von Streams auch Zyklen innerhalb des so erstellten gerichteten Graphens kreiert werden können, die vermieden werden sollten. Leider lässt sich eine Prüfung auf die Identität nicht ohne weiteres in der Form
Delphi-Quellcode:
function TMyStream.IsSame(const AStream: IStream): Boolean;
begin
Result:= (Self as IStream)=AStream;
end;
durchführen, weil Delphi das Konzept der vererbbaren Interfaces konsequent durchhält, so dass die gezeigte Methode
IsSame(...) auch mit einer Referenz auf
IInputStream aufgerufen werden kann. Es gilt aber weiterhin:
(Self as IStream)<>(Self as IInputStream)
so dass über eine Methode
GetIdentity in einem Wurzel-Interface nachgedacht werden sollte...