czwartek, 10 czerwca 2010

Obsługa I/O w Javie na przykładzie java.io

To co drażniące może być w Javie przy przejściu z innych języków. To liczne zestawienie klas do obsługi I/O (wejścia/wyjścia). Możesz się o tym przekonać odwiedzając stronę http://java.sun.com/j2se/1.4.2/docs/api/java/io/package-tree.html. Same książki nie ułatwiają ich wykorzystania ponieważ uwaga skupiona jest na zobrazowaniu listy ważniejszych klas wraz z opisem i przykładowym kodem. Pojawia się wiele wątpliwości, przy zapisie poniższego kodu:
try {
InputStream in = new BufferedInputStream(
new FileInputStream("magiczne liczby.txt"));
} catch (IOException e) {
e.printStackTrace();
}
Dlaczego teraz muszę tworzyć kilka obiektów, by móc przeczytać sobie plik? Czy to kaprys projektantów mający utrudnić życie kodującym w Javie?

Środkiem potrzebnym do uzyskania odpowiedzi jest wzorzec projektowy "dekorator". To on wyraża relacje jaka istnieje między wspomnianymi klasami. Znając go zrozumiesz korzystanie z wielu podobnych schematów.

Opis szczegółowy wzorca znajdziesz w książce Head First Design Patterns, a także na stronie http://marioosh.5dots.pl/2009/02/wzorce-projektowe-decorator/, aby go pojąć niezbędne jest zrozumienie polimorfizmu.

Przejdźmy do rzeczy, spójrz na poniższy rysunek:



Klasa OutputStream (zielona ramka) oraz klasa FilterOutputStream (czerwona ramka) służą istnieniu relacji we wzorcu dekoratora, to dzięki nim możliwe jest zestawienie klas o którym powiem za chwilę. W tym wątku przedstawię tylko możliwość korzystania z gotowej relacji. Jeżeli chcesz umieć utworzyć własną relacje dekoratora to zajrzyj do lektury.

Najistotniejsza rzecz polega na użyciu składnika (niebieska ramka) i opakowaniu go w dekoratory (fioletowa ramka). Sam dekorator na nic się nie przyda. Jednak użycie go na składniku powoduje, że sam składnik zyskuje nowe możliwości. Mieszanie składnika z dekoratorami pozwala utworzyć obiekt, który będzie zawierał porządne przez nas cechy. W ten sposób z wielu prostych klas można tworzyć złożony obiekt dostosowany do naszych potrzeb.

Co więcej, istnieje możliwość tworzenia nowych własnych dekoratorów. W przykładzie utworzę dekorator pozwalający usunąć z wejścia cyfry. Przepuszcza tylko białe znaki i litery. Należy w tym celu utworzyć klasę, która będzie dziedziczyć od FileOutputStream. Klasę nazwałem AlphaStream.



Implementacja:

Plik: AlphaStream.java
import java.io.*;

public class AlphaStream extends FilterInputStream {
public AlphaStream(InputStream in){
super(in);
}

@Override
public int read() throws IOException{
int c;

while ((c = super.read()) != -1) {
if (Character.isLetter(c) || Character.isWhitespace(c))
return c;
}
return -1;
}
}

Plik: Main.java
import java.io.*;

public class Main {

public static void main(String[] argc) {
try{
InputStream in = new AlphaStream(
new BufferedInputStream(System.in));
String buff = "";
int c;
while((c = in.read()) >= 0){
buff += (char)c;
}
System.out.println(buff);
}
catch( IOException e) {
e.printStackTrace();
}
}

}

Brak komentarzy:

Prześlij komentarz