Слово «поток» было выбрано потому, что оно представляет (в реальной жизни) значение, очень похожее на то, что мы хотим передать, когда используем его.
Давайте немного забудем о бэк-магазине и начнем думать об аналогии с водным потоком. Вы получаете непрерывный поток данных, точно так же, как вода непрерывно течет в реке. Вы не обязательно знаете, откуда поступают данные, и чаще всего вам это не нужно; будь то из файла, сокета или любого другого источника, это не имеет (не должно) никакого значения. Это очень похоже на получение потока воды, при котором вам не нужно знать, откуда он исходит; будь то озеро, фонтан или другой источник, это не имеет (не должно) большого значения.
Тем не менее, как только вы начинаете думать, что вам нужны только те данные, которые вам нужны, независимо от того, откуда они берутся, абстракции, о которых говорили другие, становятся более ясными. Вы начинаете думать, что можете обернуть потоки, и ваши методы все равно будут работать идеально. Например, вы можете сделать это:
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);
Как видите, становится очень легко изменить источник входного сигнала без изменения логики обработки. Например, чтобы прочитать данные из сетевого сокета вместо файла:
Stream stream = new NetworkStream(mySocket);
StreamReader reader = new StreamReader(stream);
int x = ReadInt(reader);
Так легко, как только может быть. И красота продолжается, так как вы можете использовать любой источник ввода, если вы можете создать для него потоковую «обертку». Вы могли бы даже сделать это:
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());
См? Пока ваш метод не заботится о том, что является источником ввода, вы можете настроить его различными способами. Абстракция позволяет очень элегантно отделить входные данные от логики обработки.
Обратите внимание, что созданный нами поток не имеет резервного хранилища, но он по-прежнему отлично подходит для наших целей.
Итак, подведем итог: поток - это просто источник ввода, скрывающий (абстрагирующий) другой источник. Пока вы не нарушите абстракцию, ваш код будет очень гибким.