— Привіт, Аміго! Сьогодні Еллі тобі розповіла про патерн адаптер.

Більшість класів, що відносяться до потоків введення-виведення, реалізовано у вигляді адаптера. Вони перетворюють або рівнозначні інтерфейси, або поєднують їх за принципом від простого до складного.

— А InputStreamReader і BufferedReader – теж адаптери? Принаймні вони дуже схожі на них за стилем використання: об'єкт після створення передається в конструктор іншого об'єкта.

— Так, InputStreamReader перетворює інтерфейс InputStream до інтерфейсу Reader. BufferedReader не адаптер у чистому вигляді, т.к. розробники Java вирішили не виділяти його методи окремий інтерфейс. Але за духом він стоїть дуже близько до них.

Замість того, щоб писати 100500 різних класів, розробники Java написали два десятки адаптерів і дозволили їх з'єднувати один з одним, як програмісту захочеться.

Такий підхід дуже зручний. Програміст завжди може написати свій клас та/або адаптер, реалізувати в ньому стандартний інтерфейс і включити його до зібраного ним ланцюжка об'єктів-адаптерів.

— Так от як воно, виявляється, все влаштовано. Замість великих складних класів – ланцюжки простих об'єктів та адаптери. А ти просто створюєш їх та з'єднуєш у правильному порядку!

— І реалізуєш те, чого не вистачає.

— Так, я розумію.

— Але взагалі-то я хотів сьогодні розповісти тобі про Reader і Writer. Це два абстрактні класи, які дуже схожі на класи InputStream та OutputStream. Але, на відміну від них, ці два класи працюють із символами. Вони читають символи та записують символи. Вони дуже зручні під час роботи з текстовою інформацією. Давай подивимося, які методи вони мають:

Методи класу Reader Що метод робить
int read(char[] cbuf);
— метод одразу читає багато символів убуфер (масив символів), поки буфер не заповниться або не закінчаться символи там, звідки він їх читає.
Метод повертає кількість реально прочитаних символів (воно може бути меншим за довжину масиву)
int read();
— метод читає один символ та повертає його як результат. Результат розширюється до int для краси. Якщо доступних символів немає, метод поверне «-1».
boolean ready();
— метод повертає true якщо є ще непрочитані символи для read
void close();
— метод «закриває» потік, що викликається після закінчення роботи з потоком.
Об'єкт виконує службові операції, пов'язані із закриттям файлу на диску тощо.
З потоку більше не можна читати дані.

— Виявляється, завдяки методу read(char[] cbuf) з Reader можна читати символи цілими блоками, а не по одному символу. Так і швидше та зручніше.

— Так. А тепер подивимося, які методи є у Writer:

Метод Що метод робить
void write(int c);< /code>
— метод записує символ. Тип int звужується до char, зайва частина просто відкидається.
void write(char[] cbuff) ;
— метод записує масив символів.
void write(String s);< /code>
— метод записує рядок. Вона просто перетворюється на масив символів і викликається другим методом.
void flush();
— якщо є дані, які зберігаються десь усередині та ще не записані, то вони записуються.
void close();
— метод «закриває» потік – викликається після закінчення роботи з потоком.
Об'єкт виконує службові операції, пов'язані із закриттям файлу на диску тощо. У потік більше не можна писати дані, flush викликається автоматично.

Важливо зрозуміти, що Reader і Writer – це абстрактні класи. Вони нічого не роблять і практично не містять коду. Усі їх методи повинні будуть реалізовуватись у класах, які будуть успадковані від них. Їхнє завдання - стандартизувати механізм взаємодії між класами. Розробникам не потрібно винаходити свої стандарти взаємодії один з одним. Набагато зручніше всім підтримувати кілька базових стандартів. Тоді класи, написані різними програмістами, зможуть легко взаємодіяти не лише з класами, написаними розробниками Java, а й із класами інших програмістів.

Стандарти – велика сила.

— Згоден. Підтримка загальних стандартів – благо для всіх.