Wzorzec projektowy Dekorator Wzorzec dekoratora to w inżynierii oprogramowania jeden ze wzorców projektowych należący do grupy wzorców strukturalnych. Pozwala na dodanie nowej funkcjonalności do istniejących klas dynamicznie podczas działania programu. Wzorzec projektowy Dekorator Wzorzec dekoratora polega na opakowaniu oryginalnej klasy w nową klasę "dekorującą". Dekoratory są alternatywą dla dziedziczenia. Dziedziczenie rozszerza zachowanie klasy w trakcie kompilacji, w przeciwieństwie do dekoratorów, które rozszerzają klasy w czasie działania programu. Ponieważ w większości obiektowych języków programowania nie można tworzyć nowych klas podczas działania programu i zwykle nie można przewidzieć z góry wszystkich kombinacji rozszerzeń klas, konieczne by było stworzenie nowej klasy dla każdej kombinacji. Dekoratory są obiektami, tworzonymi w czasie działania programu, i mogą być łączone w różne kombinacje bezpośrednio przy użyciu. Przykładem wzorca dekoratora jest implementacja strumieni I/O w Javie. Dekoratory – przykład kodu // interfejs Okno interface Okno { public void rysuj(); // rysuje Okno na ekranie public String pobierzOpis(); // zwraca opis Okna } // implementacja zwykłego okna bez pasków przewijania class ZwykłeOkno implements Okno { public void rysuj() { // rysuj okno } public String pobierzOpis() { return "zwykłe okno"; } } Dekoratory – przykład kodu c.d. // abstrakcyjna klasa dekorator - implementuje interfejs Okno abstract class OknoDekorator implements Okno { protected Okno dekorowaneOkno; // dekorowane Okno public OknoDekorator(Okno dekorowaneOkno) { this.dekorowaneOkno = dekorowaneOkno; } } // pierwszy dekorator dodający pionowe paski przewijania class PionowePrzewijanieDekorator extends OknoDekorator { public PionowePrzewijanieDekorator (Okno dekorowaneOkno) { super(dekorowaneOkno); } public void rysuj() { rysujPionowyPasekPrzewijania(); dekorowaneOkno.rysuj(); } private void rysujPionowyPasekPrzewijania() { // rysuj pionowy pasek przewijania } public String pobierzOpis() { return dekorowaneOkno.pobierzOpis() + ", z pionowym paskiem przewijania"; } } Dekoratory – przykład kodu c.d. // drugi dekorator dodający poziome paski przewijania class PoziomePrzewijanieDekorator extends OknoDekorator { public PoziomePrzewijanieDekorator (Okno dekorowaneOkno) { super(dekorowaneOkno); } public void rysuj() { rysujPoziomyPasekPrzewijania(); dekorowaneOkno.rysuj(); } private void rysujPoziomyPasekPrzewijania() { // rysuj poziomy pasek przewijania } public String pobierzOpis() { return dekorowaneOkno.pobierzOpis() + ", z poziomym paskiem przewijania"; } } public class DekorowaneOknoTest { public static void main(String[] args) { // utwórz dekorowane Okno z poziomymi i pionowymi paskami przewijania Okno dekorowaneOkno = new PoziomePrzewijanieDekorator( new PionowePrzewijanieDekorator(new ZwykłeOkno())); // wypisz opis Okna System.out.println(dekorowaneOkno.pobierzOpis()); } } Dekoratory w I/O w Javie Pisanie Dekoratorów dla I/O /*FilterInputStream to abstrakcyjny dekorator dla wszystkich *klas InputStream * *Należy zaimplementować dwie metody read(), jedną dla *czytania jednego bajta, drugą dla czytania tablicy bajtów. *Ten dekorator filtruje czytane dane tak, aby wszystkie litery były małe. **/ public class LowerCaseInputStream extends FilterInputStream { public LowerCaseInputStream(InputStream in) { super(in); } public int read() throws IOException { int c = super.read(); return (c == -1 ? c : Character.toLowerCase((char)c)); } public int read(byte[] b, int offset, int len) throws IOException { int result = super.read(b, offset, len); for (int i = offset; i < offset+result; i++) { b[i] = (byte)Character.toLowerCase((char)b[i]); } return result; } } Pisanie Dekoratorów dla I/O c.d. public class InputTest { public static void main(String[] args) throws IOException { int c; try { InputStream in = new LowerCaseInputStream( new BufferedInputStream( new FileInputStream(“test.txt”))); while((c = in.read()) >= 0) { System.out.print((char)c); } in.close(); } catch (IOException e) { e.printStackTrace(); } } } Przekierowanie wejścia/wyjścia public class RedirectOut { public static void main(String[] args) throws FileNotFoundException { File file = new File("/home/test"); PrintStream printStream = new PrintStream(new FileOutputStream(file)); System.out.println("1");//pójdzie na konsolę System.setOut(printStream); System.out.println("2");//pójdzie do pliku } } public class RedirectIn { public void main(String[] args) throws IOException { File file = new File("/home/test");//plik z wejściem InputStream readStream = new FileInputStream(file); System.in.read();//odczyta z konsoli System.setIn(readStream); System.in.read();//odczyta z pliku } } java.nio – new input/output Zbiór API oferujący narzędzia do wykonywnia intensywnych operacji wejścia/wyjścia java.nio – new input/output Bufory dla danych o typach podstawowych Kodery i dekodery dla zestawów znaków Mechanizm dopasowywania wzorców wzorowany na wyrażeniach regularnych Perl-a (java.util.regex) Kanały (Channels), nowe abstrakcyjne pojęcie I/O Interfejs dla plików wspierający blokowanie i mapowanie pamięci dla plików do wielkości Integer.MAX_VALUE (2GiB) java.nio – bufory Transfer danych w java.nio jest oparty na buforach dostępnych w java.nio.Buffer i powiązanych klasach. Klasy te reprezentują pewien ciągły obszar w pamięci oraz pewną liczbę operacji transferu danych. java.nio – przykładowe funkcje i ich implementacja Metoda flip() nie wykonuje operacji zamiany poprzez fizyczne przeniesienie danych lub stron, jeśli jest możliwość prostej zamiany miejsca wskazywania wewnętrznych wskaźników. Powoduje to wzrost wydajności. Metoda clear() nie zapewnia zerowania pamięci, ale zwraca wskaźniki w ten sposób, że wszelkie dane wchodzące do bufora będą nadpisywać stare dane sprzed wywołania clear() java.nio – więcej danych Brzmi ciekawie? Dosyć wyczerpujący artykłu na angielskiej wikipedii: http://en.wikipedia.org/wiki/New_I/O Dokumentacja: http://download.oracle.com/javase/1.4.2/docs/api/j ava/nio/package-summary.html