– Cześć, Amigo! Dzisiaj Basia opowiedziała ci o wzorcu adaptera.

Większość klas związanych ze strumieniami I/O jest implementowana jako adaptery. Albo konwertują one odpowiednie interfejsy, albo łączą je, zaczynając od prostych i przechodząc do złożonych.

– Czy InputStreamReader i BufferedReader są również adapterami? Na pewno są one bardzo podobne do adapterów, jeśli chodzi o sposób ich stosowania: Po utworzeniu obiektu, jest on przekazywany do konstruktora innej klasy.

– Tak, InputStreamReader konwertuje interfejs InputStream na interfejs Reader. BufferedReader nie jest adapterem w najczystszej postaci, ponieważ projektanci Javy postanowili nie dawać swoim metodom własnego, osobnego interfejsu. Ale to jego bratnia dusza.

Zamiast pisać miliard różnych klas, programiści Javy napisali ponad dwadzieścia adapterów i pozwolili im łączyć się ze sobą w dowolny sposób określony przez programistę.

To bardzo wygodne i efektywne. Programista może zawsze napisać klasę i/lub adapter, kazać jej zaimplementować standardowy interfejs i włączyć go do łańcucha obiektów adaptera, który buduje.

– Więc tak to wszystko działa. Zamiast dużych, złożonych klas, tworzymy łańcuchy prostych obiektów i adapterów. A potem po prostu je tworzysz i łączysz w odpowiedniej kolejności!

– I implementujesz to, czego brakuje.

– Już rozumiem.

– Ale tak naprawdę to chciałem Ci dzisiaj opowiedzieć o Reader i Writer. Są to dwie abstrakcyjne klasy, które są bardzo podobne do klas InputStream i OutputStream. Ale w przeciwieństwie do powyższych klas operują one na znakach. Odczytują i zapisują znaki. Bardzo ułatwiają pracę z danymi tekstowymi. Spójrzmy na metody, które posiadają:

Metody Reader Co robi ta metoda
int read(char[] cbuf);
– Metoda ta natychmiast wczytuje kilka znaków do bufora (tablicy znaków), dopóki bufor nie będzie pełny lub dopóki źródło nie będzie miało więcej znaków do wczytania.
Metoda zwraca liczbę rzeczywiście wczytanych znaków (która może być mniejsza niż długość tablicy).
int read();
– Ta metoda odczytuje jeden znak i go zwraca. Wynik jest rozszerzany do int ze względów estetycznych. Jeżeli nie ma dostępnych znaków, wówczas metoda zwraca -1.
boolean ready();
Metoda ta zwraca wartość true, jeśli dla wczytywanych metod istnieją jakieś niewczytane znaki
void close();
Ta metoda «zamyka» strumień. Wywołuje się ją po zakończeniu pracy ze strumieniem.
Następnie obiekt wykonuje operacje porządkowe potrzebne do zamknięcia pliku itd.
W tym momencie nie można odczytać więcej danych ze strumienia.

– Okazuje się, że metoda read(char [] cbuf) klasy Reader pozwala nam zamiast jednego znaku wczytywać naraz całe ich bloki. Jest to więc szybsze i wygodniejsze.

– Dokładnie. A teraz zobaczmy, jakie metody ma Writer:

Metoda Co robi ta metoda
void write(int c);
Ta metoda zapisuje jeden znak. Typ int jest ograniczony do typu char. Pozostała część jest zwyczajnie odrzucana.
void write(char[] cbuff);
Ta metoda zapisuje tablicę znaków.
void write(String s);
Ta metoda zapisuje ciąg. Jest on po prostu skonwertowany na tablicę znaków, po czym wywoływana jest druga metoda.
void flush();
Jeśli strumień przechowuje w sobie jakiekolwiek dane, które nie zostały jeszcze zapisane, to metoda ta wymusza ich zapis.
void close();
Ta metoda «zamyka» strumień. Wywołuje się ją po zakończeniu pracy ze strumieniem.
Następnie obiekt wykonuje operacje porządkowe potrzebne do zamknięcia pliku itd. Nie możesz już zapisywać danych w strumieniu, a polecenie flush jest wywoływane automatycznie.

Ważne jest to, aby zrozumieć, że Reader i Writer to klasy abstrakcyjne. Nie wykonują żadnych operacji i nie zawierają praktycznie żadnego kodu. Wszystkie ich metody będą musiały być zaimplementowane w klasach, które je dziedziczą. Ich zadaniem jest standaryzowanie interakcji pomiędzy klasami. Deweloperzy nie muszą wymyślać swoich własnych standardów, by umożliwić interakcję. O wiele wygodniejsze dla każdego jest utrzymanie kilku podstawowych standardów. Dzięki temu klasy napisane przez różnych programistów mogą łatwo wchodzić w interakcje nie tylko z klasami napisanymi przez programistów Java, ale także z klasami napisanymi przez innych programistów.

Standardy mają wielką moc.

– To prawda. Tworzenie wspólnych standardów jest korzystne dla wszystkich.