Słowo „strumień” zostało wybrane, ponieważ reprezentuje (w prawdziwym życiu) bardzo podobne znaczenie do tego, co chcemy przekazać, gdy go używamy.
Na chwilę zapomnijmy o sklepie z podkładami i zacznijmy myśleć o analogii do strumienia wody. Otrzymujesz ciągły przepływ danych, tak jak woda stale przepływa w rzece. Niekoniecznie wiesz, skąd pochodzą dane i najczęściej nie musisz; czy to z pliku, gniazda czy innego źródła, to nie powinno (nie powinno) mieć znaczenia. Jest to bardzo podobne do odbierania strumienia wody, dzięki czemu nie musisz wiedzieć, skąd pochodzi; czy to z jeziora, fontanny, czy innego źródła, to nie powinno (nie powinno) mieć znaczenia.
To powiedziawszy, kiedy zaczniesz myśleć, że zależy ci tylko na uzyskaniu potrzebnych danych, bez względu na to, skąd pochodzą, abstrakcje, o których mówili inni, stają się wyraźniejsze. Zaczynasz myśleć, że możesz owijać strumienie, a twoje metody będą nadal działać idealnie. Na przykład możesz to zrobić:
int ReadInt(StreamReader reader) { return Int32.Parse(reader.ReadLine()); }
// in another method:
Stream fileStream = new FileStream("My Data.dat");
Stream zipStream = new ZipDecompressorStream(fileStream);
Stream decryptedStream = new DecryptionStream(zipStream);
StreamReader reader = new StreamReader(decryptedStream);
int x = ReadInt(reader);
Jak widać, bardzo łatwo jest zmienić źródło wejściowe bez zmiany logiki przetwarzania. Na przykład, aby odczytać dane z gniazda sieciowego zamiast pliku:
Stream stream = new NetworkStream(mySocket);
StreamReader reader = new StreamReader(stream);
int x = ReadInt(reader);
Tak proste, jak to tylko możliwe. Piękno trwa, ponieważ można użyć dowolnego źródła wejściowego, o ile można zbudować dla niego „opakowanie” strumienia. Możesz nawet to zrobić:
public class RandomNumbersStreamReader : StreamReader {
private Random random = new Random();
public String ReadLine() { return random.Next().ToString(); }
}
// and to call it:
int x = ReadInt(new RandomNumbersStreamReader());
Widzieć? Dopóki twoja metoda nie dba o to, jakie jest źródło wejściowe, możesz dostosowywać swoje źródło na różne sposoby. Abstrakcja pozwala oddzielić dane wejściowe od logiki przetwarzania w bardzo elegancki sposób.
Pamiętaj, że strumień, który sami stworzyliśmy, nie ma sklepu z zapleczem, ale nadal doskonale służy naszym celom.
Podsumowując, strumień jest tylko źródłem danych wejściowych, ukrywającym (abstrakcyjnym) inne źródło. Dopóki nie złamiesz abstrakcji, twój kod będzie bardzo elastyczny.