/* Skuska z OOP, 4. jun 2008, otazka 18 Vhodne je pouzit vzor Observer. Stopky predstavuju sledovany predmet (subject)), a displeje su vlastne pozorovatelia (observers). Lahko mozno pridat dalsie zobrazenie odvodenim od rozhrania TimeDisplay alebo aj iny druh stopiek odvodenim od rozhrania StopWatch. (Kazdy typ by mal byt vo vlastnom subore.) */ public interface StopWatch { void incrementTime(); void notifyDisplays(); void addDisplay(TimeDisplay d); int getTime(); } public class SecStopWatch implements StopWatch { private int time; // cas v sekundach private List displays = new ArrayList(); // zoznam displejov public void start() { ... } // spustenie merania public void stop() { ... } // zastavenie merania public void reset() { time = 0; } // vynulovanie casu public int getTime() { // ziskanie casu return time; } public void incrementTime() { // posun casu time++; // vzdy posun o sekundu notifyDisplays(); // zaslanie notifikacie displejom } public void notifyDisplays() { // zaslanie notifikacie displejom for (TimeDisplay e : displays) { // notifikacia pojde vsetkym registrovanym displejom e.refresh(); // displej sam rozhodne co ma robit } void addDisplay(TimeDisplay d) { // registracia displeja displays.add(d); } } // Spolocne rozhranie vsetkych displejov // Mohlo obsahovat aj dalsie metody, ale metoda refresh() je nevyhnutna public interface TimeDisplay { refresh(); // aktualizacia vnutorneho stavu displeja } public class SecTimeDisplay implements TimeDisplay { private StopWatch timeSource; private int time; private int shift; public SecTimeDisplay(StopWatch w, int t) { timeSource = w; // displej musi poznat svoje stopky shift = t; // a casovy posun } public void refresh() { // aktualizacia vnutorneho stavu displeja time = timeSource.getTime(); // } public void setShift(int s) { // nastavenie posunu shift += s; } public void display() { // samotne zobrazenie - v sekundach System.out.println(time + shift); } } // DigTimeDisplay je takmer rovnaky ako SecTimeDisplay - az na zobrazenie // Spolocna struktura mohla byt v triede od ktorej by dedili obidva displeje public class DigTimeDisplay { private StopWatch timeSource; private int time; private int shift; public DigTimeDisplay(StopWatch w, int t) { timeSource = w; // displej musi poznat svoje stopky shift = t; // a casovy posun } public void refresh() { time = timeSource.getTime(); } public void setShift(int s) { shift += s; } public void display() { // samotne zobrazenie - hh:mm:ss int h = (time + shift) / 3600; int m = ((time + shift) % 3600) / 60; int s = (time + shift) % 60; System.out.println( h / 10 + h % 10 + ":" + m / 10 + m % 10 + ":" + s / 10 + s % 10 ); } } // Priklad pouzitia: // Majme jedny stopky SecStopWatch sw = new SecStopWatch(); // Tri rozne displeje budu pripojene na tieto stopky. Budu ulozene v poli pre lahsiu manipulaciu. TimeDisplay[] d = new TimeDisplay[3]; d[0] = new SecTimeDisplay(sw, 0); d[1] = new SecTimeDisplay(sw, 10); d[2] = new DigTimeDisplay(sw, -255); // Tu by sme zaradili metodu incrementTime() do planovaca na vykonanie kazdu sekundu. // Zobrazenie na displejoch je jednoduche: for (TimeDisplay e : d) display();