APNVZ_2. Vzor Model view controller, Observer

Podobné dokumenty
Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Při studiu tohoto bloku se předpokládá, že student je zvládá základy programování v jazyce Java s využitím vývojového prostředí NetBeans.

Aplikace s grafickým uživatelským rozhraním

Projekty pro výuku programování v jazyce Java

typová konverze typová inference

TÉMATICKÝ OKRUH Softwarové inženýrství

Observer. Klasifikace. Alias. Smysl. Potřeba sledování změn objektu a notifikace. Obdoba systému událostí (C#, Java) vlastními prostředky

GUI v Javě a událostmi řízené programování

GUI v Javě a událostmi řízené programování

Obsah přednášky. GUI v Javě a událostmi řízené programování. Základní prvky grafického rozhraní. Základní komponenty.

Úvod do programovacích jazyků (Java)

GUI. Systémová integrace pro desktopové aplikace

Seznamy a iterátory. Kolekce obecně. Rozhraní kolekce. Procházení kolekcí

APLIKACE NÁVRHOVÝCH VZORŮ

Obsah přednášky. GUI v Javě a událostmi řízené programování. Základní prvky grafického rozhraní. Základní komponenty.

GUI v Javě (připomínka) Návrhář GUI Příklad aplikace MVC Model-View-Controller Události Vnitřní třídy. MVC Model-View-Controller

Abstraktní datové typy: zásobník

GUI v Javě a událostmi řízené programování

UJO Framework. revoluční architektura beans. verze

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

boolean hasnext() Object next() void remove() Kolekce

OOPR_05. Případové studie

OOPR_05. Případové studie

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

Návrhové vzory Design Patterns

Java - Kresba. 2/28/11 1/8 Java - kresba

Java GUI události. Událostmi řízené programování. Zpracování = obsluha událostí

Čipové karty Lekařská informatika

Webové služby a XML. Obsah přednášky. Co jsou to webové služby. Co jsou to webové služby. Webové služby a XML

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Java - řazení objektů

Java - výjimky. private void vstup() throws IOException {... }

JAVA Unit testing Java, zimní semestr

Programování v Javě I. Leden 2008

KIV/PIA 2013 Jan Tichava

20. Projekt Domácí mediotéka

Programování v Javě I. Únor 2009

1. Programování proti rozhraní

JAVA Unit testing Java, zimní semestr

Události. A0B36PR2-Programování 2 Fakulta elektrotechnická České vysoké učení technické

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Generické programování

Abstraktní třída a rozhraní

RMI - Distribuované objekty v Javě

Přehled probírané látky

Hiearchical MVC (Model-view-controller) vs. PAC (Presentation-abstraction-control)

Typický prvek kolekce pro české řazení

Deklarace a vytváření

1. Téma 12 - Textové soubory a výjimky

7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd

Java a Caché IV: Manipulace s objekty

Java Enum Java, zimní semestr ,2017 1

Statické proměnné a metody. Tomáš Pitner, upravil Marek Šabo

Principy objektově orientovaného programování

Třídy, polymorfismus. A0B36PR2-Programování 2 Fakulta elektrotechnická České vysoké učení technické

Tvorba informačních systémů

Seminář Java II p.1/43

Vytváření a použití knihoven tříd

Bridge. Známý jako. Účel. Použitelnost. Handle/Body

Typ 2 - připojení prostřednictvím kódu nativního klienta pro přístup k síti

TŘÍDY POKRAČOVÁNÍ. Události pokračování. Příklad. public delegate void ZmenaSouradnicEventHandler (object sender, EventArgs e);

Obsah přednášky 9. Skrývání informací. Skrývání informací. Zapouzdření. Skrývání informací. Základy programování (IZAPR, IZKPR) Přednáška 9

IRAE 07/08 Přednáška č. 2. atr1 atr2. atr1 atr2 -33

PREPROCESOR POKRAČOVÁNÍ

Java a XML. 10/26/09 1/7 Java a XML

Teoretické minimum z PJV

RMI Remote Method Invocation

KTE / ZPE Informační technologie

Java Výjimky Java, zimní semestr

8. GRAFICKÉ UŽIVATELSKÉ ROZHRANÍ

Programování v C++ 2, 4. cvičení

Konstruktory a destruktory

Seminář Java IV p.1/38

Algoritmizace a programování

Databáze I. Přednáška 7

Tvorba informačních systémů

Základní pojmy. Matice(řádky, sloupce) Matice(4,6) sloupce

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Úvod Třídy Rozhraní Pole Konec. Programování v C# Hodnotové datové typy, řídící struktury. Petr Vaněček 1 / 39

Jazyk C# (seminář 6)

Google Web Toolkit. Martin Šurkovský, SUR března Katedra informatiky

Student s Life. Návrhová dokumentace (Design) Lukáš Barák, Jakub Ječmínek, Jaroslav Brchel, Jiří Zmeškal

11. Dědičnost. Dědičnost strana 103

8 Třídy, objekty, metody, předávání argumentů metod

Struktura třídy, operátory, jednoduché algoritmy, junit. Programování II 2. cvičení Alena Buchalcevová

5 Rekurze a zásobník. Rekurzivní volání metody

Swing. Přehled komponent. Java UI, letní semestr 2017/2018 1

Dalším příkladem může být například výstup dat na různá zařízení, souborů, grafických rozhraní, sítě atd.

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

Grafické uživatelské rozhraní v Javě. A0B36PR2-Programování 2 Fakulta elektrotechnická České vysoké učení technické

Výčtový typ strana 67

George J. Klir. State University of New York (SUNY) Binghamton, New York 13902, USA

Java aplety. Předávání parametrů z HTML

Tabulka symbolů. Vazba (binding) Vazba - příklad. Deklarace a definice. Miroslav Beneš Dušan Kolář

Úvod do programování - Java. Cvičení č.4

Replikace je proces kopírování a udržování databázových objektů, které tvoří distribuovaný databázový systém. Změny aplikované na jednu část jsou

Grafické uživatelské rozhraní v Javě. A0B36PR2-Programování 2 Fakulta elektrotechnická České vysoké učení technické

Komponenty v.net. Obsah přednášky

Datové struktury. Obsah přednášky: Definice pojmů. Abstraktní datové typy a jejich implementace. Algoritmizace (Y36ALG), Šumperk - 12.

Transkript:

APNVZ_2 Vzor Model view controller, Observer 1

Model-View-Controller MVC vzor architektury dělí interaktivní aplikaci na tři komponenty: Model obsahuje funkcionální jádro a data. Views (pohledy) zobrazují informace uživateli. Controllers (řízení) zpracovávají uživatelský vstup. Views a controllers spolu představují uživatelské rozhraní. Mechanismus šíření změn zabezpečí konzistenci mezi uživatelským rozhraním a modelem. 2

Model-View-Controller Kontext: Interaktivní aplikace s pružným rozhraním člověkpočítač. Problém: Uživatelské rozhraní je náchylné ke změnám požadavků. Při rozšíření funkčnosti aplikace je třeba modifikovat menu. I změna nové verze základního OS přináší změny. Klasické budování takového systému je úzce spjaté s funkcionálním jádrem. 3

Model-View-Controller Síly ovlivňující řešení: Stejné informace jsou prezentovány v různých oknech. Zobrazení a chování aplikace musí odrážet okamžitou manipulaci s daty. Změny v uživatelském rozhraní by měly být snadné a dokonce možné za běhu aplikace. Podpora různých look and feel standardů nebo portování uživatelského rozhraní by nemělo ovlivnit jádro aplikace. 4

Model-View-Controller Řešení: MVC, které dělí aplikaci na zpracování (model), výstupy (views), vstupy (controllers). Komponenta model zapouzdřuje základní data a funkcionalitu. Model je nezávislý na specifikacích vstupního a výstupního chování aplikace. 5

Model-View-Controller Komponenta View (pohled) zobrazuje uživateli informace. View dostává data od modelu. Na model může existovat několik pohledů. Každé view má asociovanou komponentu controller. Controllers obdrží událost, ta je přetransformována na požadavek služby pro model nebo view. Uživatel komunikuje se systémem výhradně prostřednictvím controlleru. 6

Model-View-Controller Separace komponenty model od komponent view a controller umožňuje násobné pohledy na stejný model. Pokud uživatel změní model prostřednictvím komponenty controller jedné komponenty view, všechny ostatní komponenty view závislé na těchto datech se také změní. Komponenta model proto uvědomuje všechny komponenty view, zda-li se jejich data změnila. Komponenty view na druhou stranu obnovují data z komponenty model a aktualizují 7

Model-View-Controller Mechanismus šíření změn udržuje seznam závislých komponent uvnitř modelu. Všechny komponenty view a také vybrané komponenty controller registrují své potřeby být informován o změnách. Změny stavu modelu spouštějí mechanismus šíření změn. Tento mechanismus je reprezentován spojením komponent model s komponentami views a controllers. 8

Model-View-Controller Komponenty view představují informace pro uživatele. Různé komponenty views prezentují informace modelu různým způsobem. Každá komponenta view definuje proceduru update, která je aktivována mechanismem šíření změn. Když je zavolána procedura update, komponenta view obnoví hodnoty aktuálních dat z modelu a zobrazí je na obrazovce. 9

Model-View-Controller Během inicializace jsou všechny komponenty view asociovány s modelem a registrovány v mechanismu šíření změn. Každá komponenta view vytváří odpovídající komponentu controller. Mezi komponentami view a controller existuje asociace jedna k jedné. 10

Základní schéma MVC Observer +update() -callupdate Model -coredata -setofobservers -attach -getdata View +attachobserver() +detachobserver() +notify() +getdata() +service() -attach -mymodel -mycontroller +initialize(model)() +makecontroller() +activate() +display() +update() -create 1 -manipulate display -callservice 1 -mymodel -myview Controller +initialize(model, View)() +handleevent() +update() 11

Základní scénář práce MVC Controller Model View handleevent service notify update display getdata update getdata 12

Inicializace MVC main program Model View initialize attach makecontroller Controller initialize attach starteventprocessing 13

Implementace 1. Oddělení interakce člověk-počítač od jádra funkcionality. 2. Implementace mechanismu šíření změn. 3. Návrh a implementace komponent views. 4. Návrh a implementace komponent controllers. 5. Návrh a implementace vztahu komponent viewcontroller. 14

Výhody / nevýhody Výhody Vícenásobné pohledy na stejný model. Synchronizované pohledy. Snadno zaměnitelné komponenty views a controllers. Slabá místa Vzrůstající složitost. Rychle rostoucí počet operací update. Neefektivnost v přístupu k datům v pohledu. 15

Aplikace monitorování počasí Manuální MVC - obrázek Humidity sensor Temperature sensor Weather Station pull data WeatherData Object displays Display device Pressure sensor implementation 16

public class WeatherData implements Subject { private float temperature; private float humidity; private float pressure; public void measurementschanged() { float temperature = gettemperature(); float humidity = gethumidity(); float pressure = getpressure(); currentconditionsdisplay.update(temperature, humidity, pressure); statisticsdisplay.update(temperature, humidity, pressure); forecastdiaplay.update(temperature, humidity, pressure); Poznámky První návrh WeatherData volání metod zabezpečí aktuální stav aktualizace displejů public float gettemperature() { return temperature; public float gethumidity() { return humidity; public float getpressure() { return pressure; 17

public class WeatherData implements Subject { Poznámky private float temperature; private float humidity; private float pressure; Kódováním konkrétní implementace, není možnost přidat, odstranit další zobrazované prvky. První návrh WeatherData public void measurementschanged() { float temperature = gettemperature(); float humidity = gethumidity(); float pressure = getpressure(); Mělo by se společné rozhraní, jedná se vždy o metodu update currentconditionsdisplay.update(temperature, humidity, pressure); statisticsdisplay.update(temperature, humidity, pressure); forecastdiaplay.update(temperature, humidity, pressure); je třeba zapouzdřit 18

Publisher + subscriber = Observer Když se změní data v objektu, ti co ho sledují observers pozorovatelé jsou o tom uvědoměni. Publisher publikuje subscriber předplatitel. Dog Object Subject Cat Object Mouse Object 19

Publisher + subscriber = Observer Vzor observer definuje relaci one-to-many mezi objektem a množinou (kolekcí objektů). Když se stav objektu změní, jsou uvědoměny všechny objekty množiny (kolekce) závislých objektů. Dog Object Subject Cat Object Mouse Object Duck Object 20

Diagram tříd vzor Observer «interface» Subject registerobserver() removeobserver() notifyobservers() observer «interface» Observer update() ConcreteSubject ConcreteObserver registerobserver() removeobserver() notifyobservers() subject update() //other Observer methods 21

Síla volné vazby loose coupling Když jsou dva objekty volně spojeny, mohou vzájemně interagovat (vzájemně se ovlivňovat), ale mají o sobě velmi málo vědomostí. Vzor observer poskytuje návrh objektů, kde objekty a observery jsou volně propojeny. Jedinou věc, kterou subjekt ví o observrech je, že implementovaly dané (jisté) rozhraní. Můžeme přidat (odebrat) další observery (pozorovatele) v libovolném čase. 22

Síla volné vazby loose coupling Nikdy nebudeme potřebovat modifikovat subjekt, aby přidal nový typ observeru. Změna buď na straně subjektu, nebo observerů neovlivní druhou stranu. 23

Návrh Weather Station «interface» Subject registerobserver() removeobserver() notifyobservers() observer «interface» Observer update() «interface» DisplayElement display() ThirdPartyDisplay WeatherData registerobserver() removeobserver() notifyobservers() gettemperature() gethumidity() getpressure() measurementchanged() subject CurrentConditionsDisplay() update() display() {//display current measurements StatisticsDisplay update() display() { // display something else based on measurements ForecastDisplay update() display() { //display the average, min and max measurements update() display() { // display the forecast 24

public interface Subject { public void registerobserver(observer o); public void removeobserver(observer o); public void notifyobservers(); Poznámky public interface Observer { public void update(float temp, float humidity, float pressure); public interface DisplayElement { public void display(); 25

public class WeatherData implements Subject { private ArrayList observers; private float temperature; private float humidity; private float pressure; Poznámky První návrh WeatherData public WeatherData() { observers = new ArrayList(); public void registerobserver(observer o) { observers.add(o); public void removeobserver(observer o) { int i = observers.indexof(o); if (i >= 0) { observers.remove(i); public void notifyobservers() { for (int i = 0; i < observers.size(); i++) { Observer observer = (Observer)observers.get(i); observer.update(temperature, humidity, pressure); 26

public void measurementschanged() { notifyobservers(); Poznámky public void setmeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementschanged(); 27

public class CurrentConditionsDisplay implements Observer, DisplayElement{ private float temperature; private float humidity; private Subject weatherdata; // vazba na weatherdata Poznámky // konstruktor public CurrentConditionsDisplay(Subject weatherdata) { this.weatherdata = weatherdata; weatherdata.registerobserver(this); public void update(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; display(); public void display() { System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity"); 28

public class WeatherStation { public static void main(string[] args) { WeatherData weatherdata = new WeatherData(); CurrentConditionsDisplay currentdisplay = new CurrentConditionsDisplay(weatherData); Poznámky Implementace Weather Station StatisticsDisplay statisticsdisplay = new StatisticsDisplay(weatherData); ForecastDisplay forecastdisplay = new ForecastDisplay(weatherData); weatherdata.setmeasurements(80, 65, 30.4f); weatherdata.setmeasurements(82, 70, 29.2f); weatherdata.setmeasurements(78, 90, 29.2f); 29

Current conditions: 80.0F degrees and 65.0% humidity Avg/Max/Min temperature = 80.0/80.0/80.0 Forecast: Improving weather on the way! Current conditions: 82.0F degrees and 70.0% humidity Avg/Max/Min temperature = 81.0/82.0/80.0 Forecast: Watch out for cooler, rainy weather Current conditions: 78.0F degrees and 90.0% humidity Avg/Max/Min temperature = 80.0/82.0/78.0 Forecast: More of the same Poznámky 30

Observer Cílem tohoto návrhového vzoru je definovat závislost one-to-many (jeden k mnoha) mezi objekty Jeden objekt sledovaný (observable); mnoho objektů sledovatelé (observers), závislé objekty Průběh sledování: když se sledovaný objekt změní, jsou o tom informováni všichni sledovatelé - závislé objekty, takže mohou reagovat na změnu. Java v tomto směru poskytuje pro sledovaný objekt třídu java.util.observable. Sledovaný objekt musí být podtřídou této třídy. 31

Jak se objekt stane Observrem (objektem, který sleduje) Implementuje rozhraní Observer a zavolá metodu addobserver() pro každý observable objekt. Podobně volá deleteobserver() pro zrušení ze seznamu. 32

Sledovaný objekt - observable Daná třída musí být podtřídou třídy Observable. 1. Nejdříve musí zavolat metodu setchanged() k oznámení, že stav sledovaného objektu se změnil. 2. Pak zavolá jednu z metod notifyobservers() notifyobservers() notifyobservers(object arg) 33

Pro observery k získání oznámení Implementují metodu update(), jejíž signatura je následující: update(observable o, Object arg); Observable je subjekt, který poslal oznámení je uložen v tomto agrumentu. Object datový objekt, který je předán z metody notityobservers. 34

setchanged() { changed = true; notifyobservers(object arg) { if(changed) { for every observer on the list { call update(this.arg) changed = false; Poznámky Co se odehrává za scénou: pseudokód notifyobservers() { notifyobservers(null) 35

Použití javovského vestavěného vzoru Observer Observable observer «interface» Observer addobserver() deleteobserver() notifyobservers() setchanged() update() WeatherData gettemperature() gethumidity() getpressure() subject GeneralDisplay update() display() StatisticsDisplay update() display() ForecastDisplay update() display() 36

import java.util.observable; import java.util.observer; Poznámky public class WeatherData extends Observable { private float temperature; private float humidity; private float pressure; public WeatherData() { public void measurementschanged() { setchanged(); notifyobservers(); public void setmeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementschanged(); public float gettemperature() { return temperature; // gethumidity(), getpressure() 37

import java.util.observable; import java.util.observer; Poznámky public class CurrentConditionsDisplay implements Observer, DisplayElement{ Observable observable; private float temperature; private float humidity; // konstruktor public CurrentConditionsDisplay(Observable observable) { this.observable = observable; observable.addobserver(this); public void update(observable obs, Object arg) { if (obs instanceof WeatherData) { WeatherData weatherdata = (WeatherData)obs; this.temperature = weatherdata.gettemperature(); this.humidity = weatherdata.gethumidity(); display(); public void display() { System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity"); 38

Observer praktická ukázka Celý návrhový vzor je demonstrován na jednoduché ukázce s jedním účtem a objekty otec a matka (typu Osoba), které na účet přispívají a objekty třídy Student, které z účtu v okamžiku, když tam přijdou peníze, peníze čerpají. V příkladu jsou uvedeni dva studenti, kteří čerpají stejným dílem. Objekt Ucet je deklarovaný jako objekt podtřídy Observable (pozorovaný objekt). Objektu třídy student implementují rozhraní Observer. 39

import java.util.observable; public class Ucet extends Observable { private int cislo; private int stav; Poznámky public Ucet() { this(0, 0, null, null); public Ucet(int cislo, int stav, Student s1, Student s2) { this.cislo = cislo; this.stav = stav; addobserver(s1); addobserver(s2); public void vlozeni (int castka) { stav = stav + castka; System.out.printf("Ucet vlozeni: %d stav: %d\n",castka, getstav()); setchanged(); notifyobservers(castka); public void vyber (int castka) { stav = stav - castka; System.out.printf("Ucet vyber: %d zustatek: %d\n",castka,getstav()); 40

public int getstav(){ return stav; public String tostring() { String tx = "Cislo uctu: " + cislo + " stav: " + stav; return tx; public void tisk() { System.out.println(this.toString()); public int getcislo(){ return cislo; Poznámky 41

public class Osoba { private String jmeno; private String bydliste; Poznámky public Osoba() { this("neuvedeno", ""); public Osoba(String jmeno, String bydliste) { this.jmeno= jmeno; this.bydliste = bydliste; public void setjmeno(string jmeno) { this.jmeno = jmeno; public String getjmeno(){ return jmeno; public void setbydliste(string bydliste) { this.bydliste = bydliste; public String getbydliste() { return bydliste; public String tostring() { return String.format("%5s %s %s %s\n", "Jmeno",getJmeno(), "bydliste:",getbydliste()); public void tiskklienta() { System.out.println(this.toString()); 42

public class Rodic extends Osoba{ private Ucet ucet; public Rodic(String jmeno, String bydliste, Ucet u){ super(jmeno, bydliste); ucet = u; Poznámky public void vlozit(int castka){ ucet.vlozeni(castka); System.out.println(getClass().getName()+" vlozil castku: "+castka); 43

import java.util.observer; import java.util.observable; public class Student extends Osoba implements Observer{ public Student(String jmeno, String bydliste){ super(jmeno, bydliste); public void update(observable ob, Object castka){ int celkem = ((Ucet)ob).getStav(); int penize; if(celkem<=0)penize = 0; else penize = (Integer)castka /2; ((Ucet)ob).vyber(penize); System.out.println(getClass().getName()+ " vybral castku: " + penize); Poznámky 44

public class TestObserver { Poznámky public static void main(string[] args) { Student karel = new Student("Karel","Praha"); Student jarmila = new Student("Jarmila","Olomouc"); Ucet ucet = new Ucet(1, 200, karel, jarmila); Rodic otec = new Rodic("Josef", "Havirov", ucet); Rodic matka = new Rodic("Alena", "Havirov", ucet); otec.vlozit(500); matka.vlozit(1200); 45

Grafické uživatelské rozhraní GUI Prvky GUI (tlačítka) jsou observable (sledované, pozorované) položky. V seznamu observerů jsou další objekty, které reagují na skutečnosti, že se s GUI prvky něco stane. Každý z observerů implementuje rozhraní ActionListener a tedy musí implementovat metodu actionperformed(). V té konkrétně specifikuje, co se stane, při dané události. 46

import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; Poznámky public class SwingObserverExample { JFrame frame; public static void main(string[] args) { SwingObserverExample example = new SwingObserverExample(); example.go(); public void go() { frame = new JFrame(); JButton button = new JButton("Should I do it?"); button.addactionlistener(new AngelListener()); button.addactionlistener(new DevilListener()); frame.getcontentpane().add(borderlayout.center, button); // Set frame properties frame.setdefaultcloseoperation(jframe.exit_on_close); frame.getcontentpane().add(borderlayout.center, button); frame.setsize(300,300); frame.setvisible(true); 47

class AngelListener implements ActionListener { public void actionperformed(actionevent event) { System.out.println("Don't do it, you might regret it!"); Poznámky class DevilListener implements ActionListener { public void actionperformed(actionevent event) { System.out.println("Come on, do it!"); 48

Slabá místa java.util.observable Observable je třída a ne rozhraní. Třída Subject musí být podtřídou Observable. nemůže přidat další nadtřídu (pouze jedna nadtřída), nemůžeme implementovat metody jako u rozhraní. 49

Příklad Bruce Eckela Další příklad, kdy je datový atribut deklarovaný jako vnitřní podtřída třídy Observable nebo kdy je datový atribut jiné třídy deklarovaný jako vnitřní třída implementující rozhraní Observer. 50

UML diagram tříd Observable «interface» Observer OpenObserver Flower -onotifier -cnotifier OpenNotifier CloseNotifier Bee +openobserver() +closeobserver() CloseObserver 51

// Demonstration of "observer" pattern. import java.util.observable; public class Flower { private boolean isopen; private OpenNotifier onotify = new OpenNotifier(); private CloseNotifier cnotify = new CloseNotifier(); // konstruktor public Flower() { isopen = false; public void open() { // Opens its petals isopen = true; onotify.notifyobservers(); cnotify.open(); public void close() { // Closes its petals isopen = false; cnotify.notifyobservers(); onotify.close(); // sledovani dvou cinnosti public Observable opening() { return onotify; public Observable closing() { return cnotify; Poznámky 52

// first observable issue private class OpenNotifier extends Observable { private boolean alreadyopen = false; public void notifyobservers() { if(isopen &&!alreadyopen) { setchanged(); super.notifyobservers(); alreadyopen = true; public void close() { alreadyopen = false; Poznámky // second observable issue private class CloseNotifier extends Observable{ private boolean alreadyclosed = false; public void notifyobservers() { if(!isopen &&!alreadyclosed) { setchanged(); super.notifyobservers(); alreadyclosed = true; public void open() { alreadyclosed = false; 53

import java.util.observable; import java.util.observer; public class Bee { private String name; private OpenObserver openobsrv = new OpenObserver(); private CloseObserver closeobsrv = new CloseObserver(); public Bee(String nm) { name = nm; // An inner class for observing openings: private class OpenObserver implements Observer{ public void update(observable ob, Object a) { System.out.println("Bee " + name + "'s breakfast time!"); // Another inner class for closings: private class CloseObserver implements Observer{ public void update(observable ob, Object a) { System.out.println("Bee " + name + "'s bed time!"); Poznámky 54

public Observer openobserver() { return openobsrv; public Observer closeobserver() { return closeobsrv; Poznámky 55

import java.util.observable; import java.util.observer; public class Hummingbird { private String name; private OpenObserver openobsrv = new OpenObserver(); private CloseObserver closeobsrv = new CloseObserver(); public Hummingbird(String nm) { name = nm; Poznámky // sledovani otevreni private class OpenObserver implements Observer{ public void update(observable ob, Object a) { System.out.println("Hummingbird " + name + "'s breakfast time!"); // sledovani zavreni private class CloseObserver implements Observer{ public void update(observable ob, Object a) { System.out.println("Hummingbird " + name + "'s bed time!"); 56

public Observer openobserver() { return openobsrv; Poznámky public Observer closeobserver() { return closeobsrv; 57

import java.util.*; Poznámky public class ObservedFlower { public static void main(string args[]) { Flower f = new Flower(); Bee ba = new Bee("BA"), bb = new Bee("BB"); Hummingbird h1 = new Hummingbird("H1"), h2 = new Hummingbird("H2"); // dve sledovane veci na kvetine Observable floweropn = f.opening(); Observable flowercls = f.closing(); // dve vcely Observer bao = ba.openobserver(); Observer bac = ba.closeobserver(); Observer bbo = bb.openobserver(); Observer bbc = bb.closeobserver(); // dva kolibrici Observer h1o = h1.openobserver(); Observer h1c = h1.closeobserver(); Observer h2o = h2.openobserver(); Observer h2c = h2.closeobserver(); 58

floweropn.addobserver(bao); floweropn.addobserver(bbo); floweropn.addobserver(h1o); floweropn.addobserver(h2o); Poznámky flowercls.addobserver(bac); flowercls.addobserver(bbc); flowercls.addobserver(h1c); flowercls.addobserver(h2c); // kolibrik h2 jeste spi floweropn.deleteobserver(h2o); f.open(); // vcela bb nechce do postele flowercls.deleteobserver(bbc); f.close(); // rusi vsecny pozorovatele otevreni floweropn.deleteobservers(); System.out.println("Nikdo nesleduje otevreni"); f.open(); f.close(); 59

Hummingbird H1's breakfast time! Bee BB's breakfast time! Bee BA's breakfast time! Hummingbird H2's bed time! Hummingbird H1's bed time! Bee BA's bed time! Nikdo nesleduje otevreni Hummingbird H2's bed time! Hummingbird H1's bed time! Bee BA's bed time! Poznámky 60

Vzor MVC a web Převažující adaptace tohoto vzoru používá kombinací servletu a technologie JSP (JavaServer Pages) k uchování oddělení modelu, pohledu a kontroleru. 1. Vytvoříte HTTP request, který přijme servlet. Tato operace typicky zahrnuje, že spolu s dotazem budou zaslána data v nějaké formě jako např. uživatelské jméno a heslo. Servlet dostane tato data a syntakticky je analyzuje (parsuje). 61

Vzor MVC a web 2. Servlet pracuje jako kontroler a zpracuje váš dotaz většinou jako další (následný) dotaz na model (v tomto případě bean/ databázi). Výsledek zpracování dotazu je obyčejně vytvořen (zformován) do formy JavaBeanu. JavaBean představuje model, protože obsahuje také tzv. business logiku tedy metody pro práci s modelem. Databáze většinou již představuje jen perzistenci vložených objektů, proto nepředstavuje model. 62

Vzor MVC a web 3. Kontroler přesouvá řízení na view (pohled). View je reprezentované JSP (JavaServer Pages). Jedinou činností JSP je vytvořit stránku, která představuje pohled modelu (view of model). 4. Tento pohled JSP získá z JavaBeanu, spolu s dalšími příkazy pro řízení nutnými pro další akce. 63

Vzor MVC a web 5. Pohled vrací stránku prohlížeči prostřednictvím protokolu HTTP. Stránka je vrácena prohlížeči, kde je zobrazena jako pohled (view). Uživatel pak zadá další požadavek, který je zpracován podobným způsobem. 64

Vzor MVC a web 1 HTTP request 2 instanciuje Webový prohlížeč servlet/controller klient HTTP response 5 3 databáze / persisted data jsp/view 4 bean/ model / business logic 65

Další využití MVC JList JList Implementuje architekturu delegát - model Deleguje pro ListModels ListModel Definuje metody Registruje/ruší registraci ListDataListener mod ifies JList no tifies ListModel 66

// PhilosophersJList.java // MVC architecture using JList with a DefaultListModel import java.awt.*; import java.awt.event.*; import javax.swing.*; public class PhilosophersJList extends JFrame { // model declaration private DefaultListModel philosophers; // view declaration private JList list; Poznámky PhilosophersJList třída DefaultListModel poskytuje základní implementaci rozhraní ListModel // PhilosophersJList constructor public PhilosophersJList() { super( "Favorite Philosophers" ); // create a DefaultListModel to store philosophers philosophers = new DefaultListModel(); philosophers.addelement( "Socrates" ); philosophers.addelement( "Plato" ); philosophers.addelement( "Aristotle" ); philosophers.addelement( "St. Thomas Aquinas" ); philosophers.addelement( "Soren Kierkegaard" ); philosophers.addelement( "Immanuel Kant" ); 67

philosophers.addelement( "Friedrich Nietzsche" ); philosophers.addelement( "Hannah Arendt" ); Poznámky // create a JList for philosophers DefaultListModel view list = new JList( philosophers ); // allow user to select only one philosopher at a time list.setselectionmode( ListSelectionModel.SINGLE_SELECTION ); // create JButton for adding philosophers JButton addbutton = new JButton( "Add Philosopher" ); addbutton.addactionlistener( new ActionListener() { public void actionperformed( ActionEvent event ) { // prompt user for new philosopher's name String name = JOptionPane.showInputDialog( PhilosophersJList.this, "Enter Name" ); ); // add new philosopher to model philosophers.addelement( name ); 68

// create JButton for removing selected philosopher JButton removebutton = new JButton( "Remove Selected Philosopher" ); Poznámky removebutton.addactionlistener( new ActionListener() { ); public void actionperformed( ActionEvent event ) { // remove selected philosopher from model philosophers.removeelement( list.getselectedvalue() ); // lay out GUI components JPanel inputpanel = new JPanel(); inputpanel.add( addbutton ); inputpanel.add( removebutton ); Container container = getcontentpane(); container.add( list, BorderLayout.CENTER ); container.add( inputpanel, BorderLayout.NORTH ); setdefaultcloseoperation( EXIT_ON_CLOSE ); setsize( 400, 300 ); setvisible( true ); // end PhilosophersJList constructor 69

// execute application public static void main( String args[] ) { new PhilosophersJList(); Poznámky 70

Poznámky Aplikace PhilosophersJList demonstrující Jlist and DefaultListModel Výstup aplikace 71

JTable JTable Implementuje architekturu delegát - model Deleguje pro TableModels TableModel Declaruje metody Obnovuje a modifikuje data mod ifie s JTable notifies TableModel 72

JTable Metoda void addtablemodellistener( TableModelListener listener) void removetablemodellistener( TableModelListener listener) Popis Přidá TableModelListener do TableModel, který uvědomuje TableModelListener o změnách v TableModelu Odstraní přidaný TableModelListener z TableModelu Class getcolumnclass( int columnindex ) Vrací objekt Class pro hodnoty ve sloupci specifikovaném columnindex int getcolumncount() String getcolumnname( int columnindex ) int getrowcount() Vrací počet sloupců v TableModelu Vrací jméno sloupce ze zadaného columnindexu Vrací počet rádků v TableModelu 73

JTable Metoda Object getvalueat( int rowindex, int columnindex ) void setvalueat( Object value, int rowindex, int columnindex ) Popis Vrací referenci na Object na hodnotu uloženou v TableModelu v daném řádku a sloupci Nastaví hodnotu uloženou v TableModelu v daném řádku a sloupci boolean iscelleditable( int rowindex, int columnindex ) Vrací true, je-li specifikovaná buňka editovatelná 74

// PhilosophersJTable.java // MVC architecture using JTable with a DefaultTableModel // Java core packages import java.awt.*; import java.awt.event.*; Poznámky PhilosophersJTable import javax.swing.*; import javax.swing.table.*; public class PhilosophersJTable extends JFrame { // model declaration private DefaultTableModel philosophers; // Jtable declaration private JTable table; // PhilosophersJTable constructor public PhilosophersJTable() { super( "Favorite Philosophers" ); // create a DefaultTableModel to store philosophers philosophers = new DefaultTableModel(); // add Columns to DefaultTableModel philosophers.addcolumn( "First Name" ); philosophers.addcolumn( "Last Name" ); philosophers.addcolumn( "Years" ); 75

// add philosopher names and dates to DefaultTableModel String[] socrates = { "Socrates", "", "469-399 B.C." ; philosophers.addrow( socrates ); Poznámky String[] plato = { "Plato", "", "428-347 B.C." ; philosophers.addrow( plato ); String[] aquinas = { "Thomas", "Aquinas", "1225-1274" ; philosophers.addrow( aquinas ); String[] kierkegaard = { "Soren", "Kierkegaard", "1813-1855" ; philosophers.addrow( kierkegaard ); String[] kant = { "Immanuel", "Kant", "1724-1804" ; philosophers.addrow( kant ); String[] nietzsche = { "Friedrich", "Nietzsche", "1844-1900" ; philosophers.addrow( nietzsche ); String[] arendt = { "Hannah", "Arendt", "1906-1975" ; philosophers.addrow( arendt ); // create a JTable for philosophers DefaultTableModel table = new JTable( philosophers ); 76

// create JButton for adding philosophers JButton addbutton = new JButton( "Add Philosopher" ); Poznámky addbutton.addactionlistener( new ActionListener() { public void actionperformed( ActionEvent event ) { // create empty array for new philosopher row String[] philosopher = { "", "", "" ; ); // add empty philosopher row to model philosophers.addrow( philosopher ); 77

// create JButton for removing selected philosopher JButton removebutton = new JButton( "Remove Selected Philosopher" ); Poznámky removebutton.addactionlistener( new ActionListener() { ); public void actionperformed( ActionEvent event ) { // remove selected philosopher from model philosophers.removerow( table.getselectedrow() ); 78

// lay out GUI components JPanel inputpanel = new JPanel(); inputpanel.add( addbutton ); inputpanel.add( removebutton ); Poznámky Container container = getcontentpane(); container.add( new JScrollPane( table ), BorderLayout.CENTER ); container.add( inputpanel, BorderLayout.NORTH ); setdefaultcloseoperation( EXIT_ON_CLOSE ); setsize( 400, 300 ); setvisible( true ); // end PhilosophersJTable constructor // execute application public static void main( String args[] ) { new PhilosophersJTable(); 79

Poznámky Výstup aplikace 80