74
1 Návrhové vzory 2 Command, Observer, Adapter, Factory (továrna) a Abstract Factory (abstraktní továrna)

Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

  • Upload
    vannhi

  • View
    230

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

1

Návrhové vzory 2

Command, Observer, Adapter, Factory (továrna) a Abstract Factory (abstraktní továrna)

Page 2: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

2Návrhový vzor CommandProblém

• Standardní cesta pro vykonání metody je jejívyvolání.

• V některých situacích nejsme schopni řídit načasování (timing) kontextu, ve kterém by se měly metody volat. Dalším problémem je flexibilní zpracování návratové hodnoty metody.

• Událostmi řízené programování – událost (event) činnost zapouzdřena do objektu.

Page 3: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

3

Command - kontext

• Klient, který využívá služeb (metod) objektu voláoperaci, která vrací návratovou hodnotu, podle které se rozhodne o dalším pokračování programu.

• Pro jednoduchost předpokládejme návrat celočíselné hodnoty např. 1 a 2 a podle jich se rozhodne jak dále.

• Samozřejmě je třeba ještě ošetřit jinou návratovou hodnotu, která způsobí chybu.

Page 4: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

4

Kontext

• Původnířešení je následující:

switch (hodnota) {

1 : a.nejakaOperace( );

2 : b.jinaOperace( );

}

• Uvedenéřešení je funkční, ale není flexibilní. Přidání další možné návratové hodnoty znamenápřepsat (doplnit) uvedený kód.

Page 5: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

5

Řešení

• Záměrem návrhového vzoru Command je zapouzdřit požadavek (operaci) do formy objektu.

• Zaveďme rozhraní s operacíexecute( ).

• Pro každé zpracování návratové hodnoty zavedeme další třídu pod tímto rozhraním a v této třídě implementujeme metodu execute( ) .

• Ta pak provede patřičné operace např. a.nejakaOperace( ).

Page 6: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

6

Řešení

• Jinými slovy zapouzdřímepožadavek (metodu) do podoby objektu (objektové proměnné), takže můžeme s požadavkem pracovat jako s každou jinou proměnnou, což vede k parametrizaci požadavků– dynamické tvorbě seznamu požadavků, dosazení

požadavku za jiný požadavek apod.

Page 7: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

7

Schéma vzoru Command pomocí UML

Page 8: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

8

Fungování vzoru Command

• Proměnná typu Command (rozhraní), může nabývat hodnot svých podtříd, tedy Command1 nebo Command2.

• Podle skutečného typu proměnné je pak vybranátřída Command1 resp. Command2 a metoda execute().

• Metoda execute() v sobě obsahuje odkaz buď na a.nejakaOperace() nebo na b,jinaOperace().

Page 9: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova9

interface interface interface interface CommandCommandCommandCommand {{{{

voidvoidvoidvoid execute();execute();execute();execute();

}}}}

classclassclassclass HelloHelloHelloHello implementsimplementsimplementsimplements CommandCommandCommandCommand {{{{

// private // private // private // private TridaATridaATridaATridaA a;a;a;a;

// // // // public public public public HelloHelloHelloHello((((TridaATridaATridaATridaA a){a){a){a){

// this a. = a; }// this a. = a; }// this a. = a; }// this a. = a; }

public public public public voidvoidvoidvoid execute() {execute() {execute() {execute() {

// // // // a.nejakaOperacea.nejakaOperacea.nejakaOperacea.nejakaOperace();();();();

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("("("("HelloHelloHelloHello ");");");");

}}}}

}}}}

classclassclassclass WorldWorldWorldWorld implementsimplementsimplementsimplements CommandCommandCommandCommand {{{{

public public public public voidvoidvoidvoid execute() {execute() {execute() {execute() {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("("("("WorldWorldWorldWorld! ");! ");! ");! ");

}}}}

}}}}

classclassclassclass IAmIAmIAmIAm implementsimplementsimplementsimplements CommandCommandCommandCommand {{{{

public public public public voidvoidvoidvoid execute() {execute() {execute() {execute() {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("I'm ("I'm ("I'm ("I'm thethethethe commandcommandcommandcommand patternpatternpatternpattern!");!");!");!");

}}}}

}}}}

Page 10: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova10

public public public public classclassclassclass CommandPatternCommandPatternCommandPatternCommandPattern{{{{

privateprivateprivateprivate RegisterCRegisterCRegisterCRegisterC rcrcrcrc = = = = newnewnewnew RegisterCRegisterCRegisterCRegisterC(6);(6);(6);(6);

public public public public voidvoidvoidvoid test(){test(){test(){test(){

rcrcrcrc....vlozitvlozitvlozitvlozit((((newnewnewnew HelloHelloHelloHello());());());());

rcrcrcrc....vlozitvlozitvlozitvlozit((((newnewnewnew WorldWorldWorldWorld());());());());

rcrcrcrc....vlozitvlozitvlozitvlozit((((newnewnewnew IAmIAmIAmIAm());());());());

}}}}

public public public public voidvoidvoidvoid run(){run(){run(){run(){

forforforfor((((intintintint i=0; i<=i=0; i<=i=0; i<=i=0; i<=rcrcrcrc....getTopgetTopgetTopgetTop(); i++)(); i++)(); i++)(); i++)

rcrcrcrc....getPrvekgetPrvekgetPrvekgetPrvek(i).execute();(i).execute();(i).execute();(i).execute();

}}}}

public static public static public static public static voidvoidvoidvoid mainmainmainmain((((StringStringStringString argsargsargsargs[]) {[]) {[]) {[]) {

CommandPatternCommandPatternCommandPatternCommandPattern cpcpcpcp = = = = newnewnewnew CommandPatternCommandPatternCommandPatternCommandPattern();();();();

cpcpcpcp.test();.test();.test();.test();

cpcpcpcp.run();.run();.run();.run();

newnewnewnew IAmIAmIAmIAm().execute(); // ().execute(); // ().execute(); // ().execute(); // jednoradkovejednoradkovejednoradkovejednoradkove resenireseniresenireseni

newnewnewnew WorldWorldWorldWorld().execute();().execute();().execute();().execute();

}}}}

} } } }

Page 11: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

11Využití vzoru Command v událostmi řízeném programování

• Programátor pouze doplňuje kód, který se mávykonat, když nastane daná událost.

Page 12: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova12

Příklad čítač – tři tlačítka

privateprivateprivateprivate classclassclassclass ButtonHandlerButtonHandlerButtonHandlerButtonHandler implementsimplementsimplementsimplements ActionListenerActionListenerActionListenerActionListener

{{{{

public public public public voidvoidvoidvoid actionPerformedactionPerformedactionPerformedactionPerformed((((ActionEventActionEventActionEventActionEvent eventeventeventevent))))

{ { { { // program// program// program// programáááátor doplntor doplntor doplntor doplníííí kkkkóóóód od od od oššššetetetetřřřřujujujujííííccccíííí danou uddanou uddanou uddanou udáááálostlostlostlost

ifififif((((eventeventeventevent....getSourcegetSourcegetSourcegetSource()==()==()==()==incrementincrementincrementincrement))))

{ c.{ c.{ c.{ c.incrincrincrincr(); (); (); (); fieldfieldfieldfield....setTextsetTextsetTextsetText((((StringStringStringString....valueOfvalueOfvalueOfvalueOf(c.(c.(c.(c.getCntgetCntgetCntgetCnt())); ())); ())); ()));

}}}}

elseelseelseelse ifififif((((eventeventeventevent....getSourcegetSourcegetSourcegetSource()==()==()==()==decrementdecrementdecrementdecrement))))

{ c.{ c.{ c.{ c.decrdecrdecrdecr(); (); (); (); fieldfieldfieldfield....setTextsetTextsetTextsetText((((StringStringStringString....valueOfvalueOfvalueOfvalueOf(c.(c.(c.(c.getCntgetCntgetCntgetCnt()));()));()));()));

}}}}

elseelseelseelse ifififif((((eventeventeventevent....getSourcegetSourcegetSourcegetSource()==()==()==()==clearclearclearclear))))

{ c.{ c.{ c.{ c.clrclrclrclr(); (); (); (); fieldfieldfieldfield....setTextsetTextsetTextsetText((((StringStringStringString....valueOfvalueOfvalueOfvalueOf(c.(c.(c.(c.getCntgetCntgetCntgetCnt())); }())); }())); }())); }

}}}}

}}}}

Page 13: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

13

Observer – Publisher/ Subscribers

• 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 ten jeden (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.

Page 14: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

14

Observer

• Dále tato třída poskytuje metody setChange() a notifyObservers(), které je třeba vyvolat při každé změne.

• Každý objekt typu Observer (sledovatel) musíbýt v úvodu zareristrovaný u objektu typu Observable pomocí metody addObserver(Observer o), která přidá objekt typu Observer do seznamu objektů, které sledujíobjekt typu Observable.

Page 15: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

15

Observer

• Objekty (observers), které sledují objekt (Observable object) musí implementovat rozhraníObserver to znamená implementovat metodu update(Observable os, Object ob) se dvěma argumenty.

• První argument je sledovaný objekt, druhý pak libovolný objekt, který může eventuálněposkytovat dodatečné informace.

Page 16: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

16

Observer – praktická ukázka

• Celý návrhový vzor je demonstrován na jednoduché ukázce s jedním účtema objekty oteca 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.

Page 17: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova17

import import import import javajavajavajava....utilutilutilutil....ObservableObservableObservableObservable;;;;

public public public public classclassclassclass UcetUcetUcetUcet extendsextendsextendsextends ObservableObservableObservableObservable {{{{

privateprivateprivateprivate intintintint cislocislocislocislo;;;;

privateprivateprivateprivate intintintint stav;stav;stav;stav;

public public public public UcetUcetUcetUcet()()()()

{{{{ thisthisthisthis(0, 0, (0, 0, (0, 0, (0, 0, nullnullnullnull, , , , nullnullnullnull););););

}}}}

public public public public UcetUcetUcetUcet((((intintintint cislocislocislocislo, , , , intintintint stav, Student s1, Student s2) { stav, Student s1, Student s2) { stav, Student s1, Student s2) { stav, Student s1, Student s2) {

thisthisthisthis....cislocislocislocislo = = = = cislocislocislocislo; ; ; ; thisthisthisthis.stav = stav;.stav = stav;.stav = stav;.stav = stav;

addObserveraddObserveraddObserveraddObserver(s1);(s1);(s1);(s1);

addObserveraddObserveraddObserveraddObserver(s2);(s2);(s2);(s2);

}}}}

public public public public voidvoidvoidvoid vlozenivlozenivlozenivlozeni ((((intintintint castkacastkacastkacastka) { ) { ) { ) {

stav = stav + stav = stav + stav = stav + stav = stav + castkacastkacastkacastka;;;;

SystemSystemSystemSystem....outoutoutout....printfprintfprintfprintf("("("("UcetUcetUcetUcet vlozenivlozenivlozenivlozeni: %d stav: %d: %d stav: %d: %d stav: %d: %d stav: %d\\\\n",n",n",n",castkacastkacastkacastka, , , , getStavgetStavgetStavgetStav());());());());

setChangedsetChangedsetChangedsetChanged(); (); (); (); notifyObserversnotifyObserversnotifyObserversnotifyObservers((((castkacastkacastkacastka););););

}}}}

public public public public voidvoidvoidvoid vyber (vyber (vyber (vyber (intintintint castkacastkacastkacastka)))) { { { {

stav = stav stav = stav stav = stav stav = stav ---- castkacastkacastkacastka;;;;

SystemSystemSystemSystem....outoutoutout....printfprintfprintfprintf("("("("UcetUcetUcetUcet vyber: %d vyber: %d vyber: %d vyber: %d zustatekzustatekzustatekzustatek: %d: %d: %d: %d\\\\n",n",n",n",castkacastkacastkacastka,,,,getStavgetStavgetStavgetStav());());());());

}}}}

Page 18: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova18

public public public public intintintint getStavgetStavgetStavgetStav(){(){(){(){

returnreturnreturnreturn stav;stav;stav;stav;

}}}}

public public public public StringStringStringString toStringtoStringtoStringtoString()()()()

{ { { { StringStringStringString txtxtxtx = "= "= "= "CisloCisloCisloCislo uctuuctuuctuuctu: " + : " + : " + : " + cislocislocislocislo + " stav: " + stav;+ " stav: " + stav;+ " stav: " + stav;+ " stav: " + stav;

returnreturnreturnreturn txtxtxtx;;;;

}}}}

public public public public voidvoidvoidvoid tisk() { tisk() { tisk() { tisk() {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln((((thisthisthisthis....toStringtoStringtoStringtoString()); ()); ()); ());

} } } }

public public public public intintintint getCislogetCislogetCislogetCislo(){(){(){(){

returnreturnreturnreturn cislocislocislocislo;;;;

}}}}

}}}}

Page 19: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova19

public public public public classclassclassclass Osoba {Osoba {Osoba {Osoba {

privateprivateprivateprivate StringStringStringString jmenojmenojmenojmeno;;;;

privateprivateprivateprivate StringStringStringString bydlistebydlistebydlistebydliste;;;;

public Osoba() { public Osoba() { public Osoba() { public Osoba() {

thisthisthisthis("neuvedeno", ""); ("neuvedeno", ""); ("neuvedeno", ""); ("neuvedeno", "");

}}}}

public Osoba(public Osoba(public Osoba(public Osoba(StringStringStringString jmenojmenojmenojmeno, , , , StringStringStringString bydlistebydlistebydlistebydliste) { ) { ) { ) {

thisthisthisthis....jmenojmenojmenojmeno= = = = jmenojmenojmenojmeno; ; ; ; thisthisthisthis....bydlistebydlistebydlistebydliste = = = = bydlistebydlistebydlistebydliste; ; ; ;

} } } }

public public public public voidvoidvoidvoid setJmenosetJmenosetJmenosetJmeno((((StringStringStringString jmenojmenojmenojmeno))))

{ { { { thisthisthisthis....jmenojmenojmenojmeno = = = = jmenojmenojmenojmeno; ; ; ; }}}}

public public public public StringStringStringString getJmenogetJmenogetJmenogetJmeno(){(){(){(){

returnreturnreturnreturn jmenojmenojmenojmeno; } ; } ; } ; }

public public public public voidvoidvoidvoid setBydlistesetBydlistesetBydlistesetBydliste((((StringStringStringString bydlistebydlistebydlistebydliste) { ) { ) { ) {

thisthisthisthis....bydlistebydlistebydlistebydliste = = = = bydlistebydlistebydlistebydliste; ; ; ;

}}}}

public public public public StringStringStringString getBydlistegetBydlistegetBydlistegetBydliste() { () { () { () {

returnreturnreturnreturn bydlistebydlistebydlistebydliste; ; ; ;

}}}}

public public public public StringStringStringString toStringtoStringtoStringtoString()()()()

{ { { { returnreturnreturnreturn StringStringStringString....formatformatformatformat("%5s %s %s %s("%5s %s %s %s("%5s %s %s %s("%5s %s %s %s\\\\n",n",n",n",

""""JmenoJmenoJmenoJmeno",",",",getJmenogetJmenogetJmenogetJmeno(), "(), "(), "(), "bydlistebydlistebydlistebydliste:",:",:",:",getBydlistegetBydlistegetBydlistegetBydliste()); }()); }()); }()); }

public public public public voidvoidvoidvoid tiskKlientatiskKlientatiskKlientatiskKlienta()()()()

{ { { { SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln((((thisthisthisthis....toStringtoStringtoStringtoString()); }()); }()); }()); }

}}}}

Page 20: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova20

public public public public classclassclassclass RodicRodicRodicRodic extendsextendsextendsextends Osoba{Osoba{Osoba{Osoba{

privateprivateprivateprivate UcetUcetUcetUcet ucetucetucetucet;;;;

public public public public RodicRodicRodicRodic((((StringStringStringString jmenojmenojmenojmeno, , , , StringStringStringString bydlistebydlistebydlistebydliste, , , , UcetUcetUcetUcet u){u){u){u){

super(super(super(super(jmenojmenojmenojmeno, , , , bydlistebydlistebydlistebydliste););););

ucetucetucetucet = u;= u;= u;= u;

}}}}

public public public public voidvoidvoidvoid vlozitvlozitvlozitvlozit((((intintintint castkacastkacastkacastka){){){){

ucetucetucetucet....vlozenivlozenivlozenivlozeni((((castkacastkacastkacastka););););

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln((((getClassgetClassgetClassgetClass().().().().getNamegetNamegetNamegetName()+" ()+" ()+" ()+" vlozilvlozilvlozilvlozil castkucastkucastkucastku: "+: "+: "+: "+castkacastkacastkacastka););););

}}}}

}}}}

Page 21: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova21

import import import import javajavajavajava....utilutilutilutil....ObserverObserverObserverObserver;;;;

import import import import javajavajavajava....utilutilutilutil....ObservableObservableObservableObservable;;;;

public public public public classclassclassclass Student Student Student Student extendsextendsextendsextends Osoba Osoba Osoba Osoba implementsimplementsimplementsimplements ObserverObserverObserverObserver{{{{

public Student(public Student(public Student(public Student(StringStringStringString jmenojmenojmenojmeno, , , , StringStringStringString bydlistebydlistebydlistebydliste){){){){

super(super(super(super(jmenojmenojmenojmeno, , , , bydlistebydlistebydlistebydliste););););

}}}}

public public public public voidvoidvoidvoid update(update(update(update(ObservableObservableObservableObservable ob, ob, ob, ob, ObjectObjectObjectObject castkacastkacastkacastka){){){){

intintintint celkem = celkem = celkem = celkem = ((((((((UcetUcetUcetUcet)ob).)ob).)ob).)ob).getStavgetStavgetStavgetStav();();();();

intintintint penizepenizepenizepenize;;;;

ifififif(celkem<=0)(celkem<=0)(celkem<=0)(celkem<=0)penizepenizepenizepenize = 0;= 0;= 0;= 0;

elseelseelseelse penizepenizepenizepenize = = = = ((((IntegerIntegerIntegerInteger))))castkacastkacastkacastka /2;/2;/2;/2;

((((((((UcetUcetUcetUcet)ob).vyber()ob).vyber()ob).vyber()ob).vyber(penizepenizepenizepenize););););

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln((((getClassgetClassgetClassgetClass().().().().getNamegetNamegetNamegetName()+ " vybral ()+ " vybral ()+ " vybral ()+ " vybral castkucastkucastkucastku: " + : " + : " + : " + penizepenizepenizepenize););););

}}}}

}}}}

Page 22: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova22

public public public public classclassclassclass TestObserverTestObserverTestObserverTestObserver {{{{

public static public static public static public static voidvoidvoidvoid mainmainmainmain((((StringStringStringString[] [] [] [] argsargsargsargs) {) {) {) {

Student Student Student Student karelkarelkarelkarel = = = = newnewnewnew Student("Karel","Praha");Student("Karel","Praha");Student("Karel","Praha");Student("Karel","Praha");

Student Student Student Student jarmilajarmilajarmilajarmila = = = = newnewnewnew Student("Jarmila","Olomouc");Student("Jarmila","Olomouc");Student("Jarmila","Olomouc");Student("Jarmila","Olomouc");

UcetUcetUcetUcet ucetucetucetucet = = = = newnewnewnew UcetUcetUcetUcet(1, 200, (1, 200, (1, 200, (1, 200, karelkarelkarelkarel, , , , jarmilajarmilajarmilajarmila););););

RodicRodicRodicRodic otec = otec = otec = otec = newnewnewnew RodicRodicRodicRodic("Josef", "("Josef", "("Josef", "("Josef", "HavirovHavirovHavirovHavirov", ", ", ", ucetucetucetucet););););

RodicRodicRodicRodic matka = matka = matka = matka = newnewnewnew RodicRodicRodicRodic("Alena", "("Alena", "("Alena", "("Alena", "HavirovHavirovHavirovHavirov", ", ", ", ucetucetucetucet););););

otec.otec.otec.otec.vlozitvlozitvlozitvlozit(500);(500);(500);(500);

matka.matka.matka.matka.vlozitvlozitvlozitvlozit(1200);(1200);(1200);(1200);

}}}}

}}}}

Page 23: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

23Využití vzoru Observer projednoduchý čítač v prost ředí GUI

• Model – objekt typu Observable

• Views – objekty typu Observer, sledují model a při každé změně tuto změnu automaticky zobrazí.

• Výhodné při více různých pohledech na stejnádata

Page 24: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova24

import import import import javajavajavajava....utilutilutilutil....ObservableObservableObservableObservable;;;;

import import import import javajavajavajava....utilutilutilutil....ObserverObserverObserverObserver;;;;

public public public public classclassclassclass CounterCounterCounterCounter extendsextendsextendsextends ObservableObservableObservableObservable {{{{

privateprivateprivateprivate intintintint cntcntcntcnt = 0;= 0;= 0;= 0;

public public public public CounterCounterCounterCounter((((ObserverObserverObserverObserver ob){ob){ob){ob){

super(); super(); super(); super();

addObserver(ob);addObserver(ob);addObserver(ob);addObserver(ob);

}}}}

public public public public voidvoidvoidvoid incrincrincrincr() {() {() {() {

cntcntcntcnt++; ++; ++; ++;

setChangedsetChangedsetChangedsetChanged(); (); (); (); notifyObserversnotifyObserversnotifyObserversnotifyObservers();();();(); }}}}

public public public public voidvoidvoidvoid decrdecrdecrdecr() {() {() {() {cntcntcntcnt--------; ; ; ;

setChangedsetChangedsetChangedsetChanged(); (); (); (); notifyObserversnotifyObserversnotifyObserversnotifyObservers(); (); (); (); }}}}

public public public public voidvoidvoidvoid clrclrclrclr() {() {() {() {cntcntcntcnt = 0; = 0; = 0; = 0;

setChangedsetChangedsetChangedsetChanged(); (); (); (); notifyObserversnotifyObserversnotifyObserversnotifyObservers();();();(); }}}}

public public public public intintintint getCntgetCntgetCntgetCnt() {() {() {() {returnreturnreturnreturn cntcntcntcnt; }; }; }; }

}}}}

Page 25: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova25

import import import import javajavajavajava....awtawtawtawt....FlowLayoutFlowLayoutFlowLayoutFlowLayout;;;;

import import import import javajavajavajava....awtawtawtawt....GridLayoutGridLayoutGridLayoutGridLayout;;;;

import import import import javajavajavajava....awtawtawtawt....BorderLayoutBorderLayoutBorderLayoutBorderLayout;;;;

import import import import javajavajavajava....awtawtawtawt....eventeventeventevent....ActionListenerActionListenerActionListenerActionListener;;;;

import import import import javajavajavajava....awtawtawtawt....eventeventeventevent....ActionEventActionEventActionEventActionEvent;;;;

import import import import javaxjavaxjavaxjavax.swing..swing..swing..swing.JFrameJFrameJFrameJFrame;;;;

import import import import javaxjavaxjavaxjavax.swing..swing..swing..swing.JTextFieldJTextFieldJTextFieldJTextField;;;;

import import import import javaxjavaxjavaxjavax.swing..swing..swing..swing.JLabelJLabelJLabelJLabel;;;;

import import import import javaxjavaxjavaxjavax.swing..swing..swing..swing.JButtonJButtonJButtonJButton;;;;

import import import import javaxjavaxjavaxjavax.swing..swing..swing..swing.JPanelJPanelJPanelJPanel;;;;

import import import import javajavajavajava....utilutilutilutil....ObserverObserverObserverObserver;;;;

import import import import javajavajavajava....utilutilutilutil....ObservableObservableObservableObservable;;;;

public public public public classclassclassclass CounterFrameCounterFrameCounterFrameCounterFrame extendsextendsextendsextends JFrameJFrameJFrameJFrame implementsimplementsimplementsimplements ObserverObserverObserverObserver{{{{

privateprivateprivateprivate CounterCounterCounterCounter c;c;c;c;

privateprivateprivateprivate JButtonJButtonJButtonJButton incrementincrementincrementincrement, , , , decrementdecrementdecrementdecrement, , , , clearclearclearclear;;;;

privateprivateprivateprivate JTextFieldJTextFieldJTextFieldJTextField fieldfieldfieldfield;;;;

privateprivateprivateprivate JLabelJLabelJLabelJLabel labellabellabellabel;;;;

privateprivateprivateprivate JPanelJPanelJPanelJPanel panel;panel;panel;panel;

public public public public CounterFrameCounterFrameCounterFrameCounterFrame() {() {() {() {

super("super("super("super("SimpleSimpleSimpleSimple countercountercountercounter");");");");

setLayoutsetLayoutsetLayoutsetLayout((((newnewnewnew FlowLayoutFlowLayoutFlowLayoutFlowLayout());());());());

labellabellabellabel = = = = newnewnewnew JLabelJLabelJLabelJLabel("("("("CounterCounterCounterCounter statestatestatestate: ");: ");: ");: ");

addaddaddadd((((labellabellabellabel););););

fieldfieldfieldfield = = = = newnewnewnew JTextFieldJTextFieldJTextFieldJTextField(6);(6);(6);(6);

fieldfieldfieldfield....setEditablesetEditablesetEditablesetEditable((((falsefalsefalsefalse););););

fieldfieldfieldfield....setHorizontalAlignmentsetHorizontalAlignmentsetHorizontalAlignmentsetHorizontalAlignment((((JTextFieldJTextFieldJTextFieldJTextField.RIGHT);.RIGHT);.RIGHT);.RIGHT);

addaddaddadd((((fieldfieldfieldfield););););

Page 26: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova26

fieldfieldfieldfield....setTextsetTextsetTextsetText("0");("0");("0");("0");

panel = panel = panel = panel = newnewnewnew JPanelJPanelJPanelJPanel();();();();

panel.panel.panel.panel.setLayoutsetLayoutsetLayoutsetLayout((((newnewnewnew GridLayoutGridLayoutGridLayoutGridLayout(1,3));(1,3));(1,3));(1,3));

incrementincrementincrementincrement = = = = newnewnewnew JButtonJButtonJButtonJButton("("("("IncrementIncrementIncrementIncrement");");");");

panel.panel.panel.panel.addaddaddadd((((incrementincrementincrementincrement););););

decrementdecrementdecrementdecrement = = = = newnewnewnew JButtonJButtonJButtonJButton("("("("DecrementDecrementDecrementDecrement");");");");

panel.panel.panel.panel.addaddaddadd((((decrementdecrementdecrementdecrement););););

clearclearclearclear = = = = newnewnewnew JButtonJButtonJButtonJButton("("("("ClearClearClearClear");");");");

panel.panel.panel.panel.addaddaddadd((((clearclearclearclear););););

addaddaddadd(panel, (panel, (panel, (panel, BorderLayoutBorderLayoutBorderLayoutBorderLayout.SOUTH);.SOUTH);.SOUTH);.SOUTH);

ButtonHandlerButtonHandlerButtonHandlerButtonHandler handlerhandlerhandlerhandler = = = = newnewnewnew ButtonHandlerButtonHandlerButtonHandlerButtonHandler();();();();

incrementincrementincrementincrement....addActionListeneraddActionListeneraddActionListeneraddActionListener((((handlerhandlerhandlerhandler););););

decrementdecrementdecrementdecrement....addActionListeneraddActionListeneraddActionListeneraddActionListener((((handlerhandlerhandlerhandler););););

clearclearclearclear....addActionListeneraddActionListeneraddActionListeneraddActionListener((((handlerhandlerhandlerhandler););););

} } } }

Page 27: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova27

privateprivateprivateprivate classclassclassclass ButtonHandlerButtonHandlerButtonHandlerButtonHandler implementsimplementsimplementsimplements ActionListenerActionListenerActionListenerActionListener {{{{

public public public public voidvoidvoidvoid actionPerformedactionPerformedactionPerformedactionPerformed((((ActionEventActionEventActionEventActionEvent eventeventeventevent) {) {) {) {

ifififif((((eventeventeventevent....getSourcegetSourcegetSourcegetSource()==()==()==()==incrementincrementincrementincrement))))

{ c.{ c.{ c.{ c.incrincrincrincr(); (); (); ();

////////fieldfieldfieldfield....setTextsetTextsetTextsetText((((StringStringStringString....valueOfvalueOfvalueOfvalueOf(c.(c.(c.(c.getCntgetCntgetCntgetCnt()));()));()));()));

}}}}

elseelseelseelse ifififif((((eventeventeventevent....getSourcegetSourcegetSourcegetSource()==()==()==()==decrementdecrementdecrementdecrement))))

{ c.{ c.{ c.{ c.decrdecrdecrdecr(); (); (); ();

////////fieldfieldfieldfield....setTextsetTextsetTextsetText((((StringStringStringString....valueOfvalueOfvalueOfvalueOf(c.(c.(c.(c.getCntgetCntgetCntgetCnt()));()));()));()));

}}}}

elseelseelseelse ifififif((((eventeventeventevent....getSourcegetSourcegetSourcegetSource()==()==()==()==clearclearclearclear))))

{ c.{ c.{ c.{ c.clrclrclrclr(); (); (); ();

////////fieldfieldfieldfield....setTextsetTextsetTextsetText((((StringStringStringString....valueOfvalueOfvalueOfvalueOf(c.(c.(c.(c.getCntgetCntgetCntgetCnt()));()));()));()));

}}}}

}}}}

}}}}

public public public public voidvoidvoidvoid setCountersetCountersetCountersetCounter((((CounterCounterCounterCounter c){c){c){c){

thisthisthisthis.c = c;.c = c;.c = c;.c = c;

}}}}

public public public public voidvoidvoidvoid update(update(update(update(ObservableObservableObservableObservable ob, ob, ob, ob, ObjectObjectObjectObject objectobjectobjectobject){){){){

fieldfieldfieldfield....setTextsetTextsetTextsetText((((StringStringStringString....valueOfvalueOfvalueOfvalueOf((((((((((((CounterCounterCounterCounter)ob).)ob).)ob).)ob).getCntgetCntgetCntgetCnt()));()));()));()));

}}}}

}}}}

Page 28: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova28

import import import import javaxjavaxjavaxjavax.swing..swing..swing..swing.JFrameJFrameJFrameJFrame;;;;

public public public public classclassclassclass CounterFrameTestCounterFrameTestCounterFrameTestCounterFrameTest {{{{

public static public static public static public static voidvoidvoidvoid mainmainmainmain((((StringStringStringString argsargsargsargs[])[])[])[])

{{{{

CounterFrameCounterFrameCounterFrameCounterFrame counterFramecounterFramecounterFramecounterFrame= = = = newnewnewnew CounterFrameCounterFrameCounterFrameCounterFrame();();();();

CounterCounterCounterCounter c = c = c = c = newnewnewnew CounterCounterCounterCounter((((counterFramecounterFramecounterFramecounterFrame););););

counterFramecounterFramecounterFramecounterFrame....setCountersetCountersetCountersetCounter(c);(c);(c);(c);

counterFramecounterFramecounterFramecounterFrame....setDefaultCloseOperationsetDefaultCloseOperationsetDefaultCloseOperationsetDefaultCloseOperation

((((JFrameJFrameJFrameJFrame.EXIT_ON_CLOSE);.EXIT_ON_CLOSE);.EXIT_ON_CLOSE);.EXIT_ON_CLOSE);

counterFramecounterFramecounterFramecounterFrame....setSizesetSizesetSizesetSize(400, 200);(400, 200);(400, 200);(400, 200);

counterFramecounterFramecounterFramecounterFrame....setVisiblesetVisiblesetVisiblesetVisible((((truetruetruetrue););););

}}}}

}}}}

Page 29: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

29

Adapter

• Kontext:• při vývoji aplikace je k dispozici nějaká třída k

použití, ale tato třída „nepasuje“ do existujících struktur – třída nepodporuje existující rozhraní

• Problém:• jak využít existující třídu, která nějak nezapadá do

existující struktury• Řešení:• zavést objekt jako spojku mezi klienta, který

očekává určité rozhraní a nekompatibilní rozhranídané třídy, takže klient může využívat neznámérozhraní

Page 30: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

30

Adapter

• Záměrem vzoru Adapter je poskytnout (zpřístupnit) rozhraní, které očekává klient zatímco používá služby třídy s odlišným rozhraním

Page 31: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

31

Adapter – diagram UML

Client

+reguiredMethod()

«rozhraní»

RequiredInterface

+reqiuredMethod()

Adapter

+usefulMethod()

ExistingClass

1 1

• Třída Adapter splňuje požadavky třídy Client

Page 32: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

32

Object Adapter – jednodušší varianta

Page 33: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova33

Simple Adapter

classclassclassclass TargetTargetTargetTarget {{{{

public public public public voidvoidvoidvoid requestrequestrequestrequest() {}() {}() {}() {}

}}}}

classclassclassclass AdapteeAdapteeAdapteeAdaptee {{{{

public public public public voidvoidvoidvoid specificRequestspecificRequestspecificRequestspecificRequest() {() {() {() {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("("("("AdapteeAdapteeAdapteeAdaptee: : : : SpecificRequestSpecificRequestSpecificRequestSpecificRequest");");");");

}}}}

}}}}

classclassclassclass Adapter Adapter Adapter Adapter extendsextendsextendsextends TargetTargetTargetTarget {{{{

privateprivateprivateprivate AdapteeAdapteeAdapteeAdaptee adapteeadapteeadapteeadaptee;;;;

public Adapter(public Adapter(public Adapter(public Adapter(AdapteeAdapteeAdapteeAdaptee a) {a) {a) {a) {

adapteeadapteeadapteeadaptee = a;= a;= a;= a;

}}}}

public public public public voidvoidvoidvoid requestrequestrequestrequest() {() {() {() {

adapteeadapteeadapteeadaptee....specificRequestspecificRequestspecificRequestspecificRequest();();();();

}}}}

}}}}

public public public public classclassclassclass SimpleAdapterSimpleAdapterSimpleAdapterSimpleAdapter {{{{

AdapteeAdapteeAdapteeAdaptee a = a = a = a = newnewnewnew AdapteeAdapteeAdapteeAdaptee();();();();

TargetTargetTargetTarget t = t = t = t = newnewnewnew Adapter(a);Adapter(a);Adapter(a);Adapter(a);

public public public public voidvoidvoidvoid test() {test() {test() {test() {

t.t.t.t.requestrequestrequestrequest();();();();

}}}}

public static public static public static public static voidvoidvoidvoid mainmainmainmain((((StringStringStringString argsargsargsargs[]) {[]) {[]) {[]) {

SimpleAdapterSimpleAdapterSimpleAdapterSimpleAdapter sasasasa = = = = newnewnewnew SimpleAdapterSimpleAdapterSimpleAdapterSimpleAdapter();();();();

sasasasa.test();.test();.test();.test();

}}}}

} } } }

Page 34: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

34

Class a Object Adapter

• předchozí případy využívaly tzv. class Adapteru, vlastní Adapter je podtřídou třídy, jejíž operaci požadujeme

• class Adapter:– implementuje požadované rozhraní– je podtřídou požadované třídy

• tento přístup vždy nefunguje, zejména kdyžmnožina metod, kterou potřebujeme adaptovat, není specifikována v rozhraní

• tehdy se použije object Adapter – používádelegování, místo subclassing (aby se stal podtřídou)

Page 35: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

35

Object Adapter

Page 36: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

36

Simple Adapter – diagram t říd

Page 37: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

37

Kontrétní p říklad

Page 38: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova38

import import import import junitjunitjunitjunit....frameworkframeworkframeworkframework.*;.*;.*;.*;

classclassclassclass WhatIHaveWhatIHaveWhatIHaveWhatIHave {{{{

public public public public voidvoidvoidvoid g() {}g() {}g() {}g() {}

public public public public voidvoidvoidvoid h() {}h() {}h() {}h() {}

}}}}

interface interface interface interface WhatIWantWhatIWantWhatIWantWhatIWant {{{{

voidvoidvoidvoid f();f();f();f();

}}}}

classclassclassclass SurrogateAdapterSurrogateAdapterSurrogateAdapterSurrogateAdapter implementsimplementsimplementsimplements WhatIWantWhatIWantWhatIWantWhatIWant {{{{

WhatIHaveWhatIHaveWhatIHaveWhatIHave whatIHavewhatIHavewhatIHavewhatIHave;;;;

public public public public SurrogateAdapterSurrogateAdapterSurrogateAdapterSurrogateAdapter((((WhatIHaveWhatIHaveWhatIHaveWhatIHave wihwihwihwih) {) {) {) {

whatIHavewhatIHavewhatIHavewhatIHave = = = = wihwihwihwih;;;;

}}}}

public public public public voidvoidvoidvoid f() {f() {f() {f() {

// // // // ImplementImplementImplementImplement behaviorbehaviorbehaviorbehavior usingusingusingusing

// // // // methodsmethodsmethodsmethods in in in in WhatIHaveWhatIHaveWhatIHaveWhatIHave::::

whatIHavewhatIHavewhatIHavewhatIHave.g();.g();.g();.g();

whatIHavewhatIHavewhatIHavewhatIHave.h();.h();.h();.h();

}}}}

}}}}

classclassclassclass WhatIUseWhatIUseWhatIUseWhatIUse {{{{

public public public public voidvoidvoidvoid op(op(op(op(WhatIWantWhatIWantWhatIWantWhatIWant wiwwiwwiwwiw) {) {) {) {

wiwwiwwiwwiw.f();.f();.f();.f();

}}}}

}}}}

Page 39: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova39

// // // // ApproachApproachApproachApproach 2: 2: 2: 2: buildbuildbuildbuild adapter use adapter use adapter use adapter use intointointointo op():op():op():op():

classclassclassclass WhatIUse2 WhatIUse2 WhatIUse2 WhatIUse2 extendsextendsextendsextends WhatIUseWhatIUseWhatIUseWhatIUse {{{{

public public public public voidvoidvoidvoid op(op(op(op(WhatIHaveWhatIHaveWhatIHaveWhatIHave wihwihwihwih) {) {) {) {

newnewnewnew SurrogateAdapterSurrogateAdapterSurrogateAdapterSurrogateAdapter((((wihwihwihwih).f();).f();).f();).f();

}}}}

}}}}

// // // // ApproachApproachApproachApproach 3: 3: 3: 3: buildbuildbuildbuild adapter adapter adapter adapter intointointointo WhatIHaveWhatIHaveWhatIHaveWhatIHave::::

classclassclassclass WhatIHave2 WhatIHave2 WhatIHave2 WhatIHave2 extendsextendsextendsextends WhatIHaveWhatIHaveWhatIHaveWhatIHave

implementsimplementsimplementsimplements WhatIWantWhatIWantWhatIWantWhatIWant {{{{

public public public public voidvoidvoidvoid f() {f() {f() {f() {

g();g();g();g();

h();h();h();h();

}}}}

}}}}

// // // // ApproachApproachApproachApproach 4: use 4: use 4: use 4: use anananan innerinnerinnerinner classclassclassclass::::

classclassclassclass WhatIHave3 WhatIHave3 WhatIHave3 WhatIHave3 extendsextendsextendsextends WhatIHaveWhatIHaveWhatIHaveWhatIHave {{{{

privateprivateprivateprivate classclassclassclass InnerAdapterInnerAdapterInnerAdapterInnerAdapter implementsimplementsimplementsimplements WhatIWantWhatIWantWhatIWantWhatIWant{{{{

public public public public voidvoidvoidvoid f() {f() {f() {f() {

g();g();g();g();

h();h();h();h();

}}}}

}}}}

public public public public WhatIWantWhatIWantWhatIWantWhatIWant whatIWantwhatIWantwhatIWantwhatIWant() { () { () { () {

returnreturnreturnreturn newnewnewnew InnerAdapterInnerAdapterInnerAdapterInnerAdapter(); (); (); ();

}}}}

}}}}

Page 40: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova40

public public public public classclassclassclass AdapterVariationsAdapterVariationsAdapterVariationsAdapterVariations extendsextendsextendsextends TestCaseTestCaseTestCaseTestCase {{{{

WhatIUseWhatIUseWhatIUseWhatIUse whatIUsewhatIUsewhatIUsewhatIUse = = = = newnewnewnew WhatIUseWhatIUseWhatIUseWhatIUse();();();();

WhatIHaveWhatIHaveWhatIHaveWhatIHave whatIHavewhatIHavewhatIHavewhatIHave = = = = newnewnewnew WhatIHaveWhatIHaveWhatIHaveWhatIHave();();();();

WhatIWantWhatIWantWhatIWantWhatIWant adaptadaptadaptadapt= = = = newnewnewnew SurrogateAdapterSurrogateAdapterSurrogateAdapterSurrogateAdapter((((whatIHavewhatIHavewhatIHavewhatIHave););););

WhatIUse2 WhatIUse2 WhatIUse2 WhatIUse2 whatIUse2whatIUse2whatIUse2whatIUse2 = = = = newnewnewnew WhatIUse2();WhatIUse2();WhatIUse2();WhatIUse2();

WhatIHave2 WhatIHave2 WhatIHave2 WhatIHave2 whatIHave2whatIHave2whatIHave2whatIHave2 = = = = newnewnewnew WhatIHave2();WhatIHave2();WhatIHave2();WhatIHave2();

WhatIHave3 WhatIHave3 WhatIHave3 WhatIHave3 whatIHave3whatIHave3whatIHave3whatIHave3 = = = = newnewnewnew WhatIHave3();WhatIHave3();WhatIHave3();WhatIHave3();

public public public public voidvoidvoidvoid test() {test() {test() {test() {

whatIUsewhatIUsewhatIUsewhatIUse.op(.op(.op(.op(adaptadaptadaptadapt););););

// // // // ApproachApproachApproachApproach 2:2:2:2:

whatIUse2.op(whatIUse2.op(whatIUse2.op(whatIUse2.op(whatIHavewhatIHavewhatIHavewhatIHave););););

// // // // ApproachApproachApproachApproach 3:3:3:3:

whatIUsewhatIUsewhatIUsewhatIUse.op(whatIHave2);.op(whatIHave2);.op(whatIHave2);.op(whatIHave2);

// // // // ApproachApproachApproachApproach 4:4:4:4:

whatIUsewhatIUsewhatIUsewhatIUse.op(whatIHave3..op(whatIHave3..op(whatIHave3..op(whatIHave3.whatIWantwhatIWantwhatIWantwhatIWant());());());());

}}}}

public static public static public static public static voidvoidvoidvoid mainmainmainmain((((StringStringStringString argsargsargsargs[]) {[]) {[]) {[]) {

junitjunitjunitjunit....textuitextuitextuitextui....TestRunnerTestRunnerTestRunnerTestRunner.run(.run(.run(.run(AdapterVariationsAdapterVariationsAdapterVariationsAdapterVariations....classclassclassclass););););

}}}}

} } } }

Page 41: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

41

Adaptace dat pro JTable

• JTable – princip práce vychází ze vzoru MVC s tím, že controller a view jsou v jedné komponentě

JTable a model je v komponentě TableModel

• TableModel uvědomuje o změnách komponentu view v JTable

• JTable (komponenta Controller) modifikuje data v komponentě TableModel

Page 42: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

42

JTable princip

• JTable– Implementuje architekturu delegat-model

– Má pravomoc pro TableModels

• TableModel– Declaruje metody

• Obnovuje modifikovaná data

not ifies

mod if ie s

JTable TableModel

JTable a TableModel architektura delegát-model

Page 43: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova43

public class public class public class public class RocketTableModelRocketTableModelRocketTableModelRocketTableModel extends extends extends extends AbstractTableModelAbstractTableModelAbstractTableModelAbstractTableModel {{{{

protected Rocket[] rockets;protected Rocket[] rockets;protected Rocket[] rockets;protected Rocket[] rockets;

protected String[] protected String[] protected String[] protected String[] columnNamescolumnNamescolumnNamescolumnNames = new String[] { "Name", "Price", = new String[] { "Name", "Price", = new String[] { "Name", "Price", = new String[] { "Name", "Price",

"Apogee" };"Apogee" };"Apogee" };"Apogee" };

public public public public RocketTableModel(RocketRocketTableModel(RocketRocketTableModel(RocketRocketTableModel(Rocket[] rockets) {[] rockets) {[] rockets) {[] rockets) {

this.rocketsthis.rocketsthis.rocketsthis.rockets = rockets;= rockets;= rockets;= rockets;

}}}}

public public public public intintintint getColumnCountgetColumnCountgetColumnCountgetColumnCount() {() {() {() {

return return return return columnNames.lengthcolumnNames.lengthcolumnNames.lengthcolumnNames.length;;;;

}}}}

//////// @@@@paramparamparamparam index which column is interestingindex which column is interestingindex which column is interestingindex which column is interesting

// // // // @return the name of the indicated column@return the name of the indicated column@return the name of the indicated column@return the name of the indicated column

public String public String public String public String getColumnName(intgetColumnName(intgetColumnName(intgetColumnName(int i) {i) {i) {i) {

return return return return columnNames[icolumnNames[icolumnNames[icolumnNames[i];];];];

}}}}

//////// @return the number of rows in this table.@return the number of rows in this table.@return the number of rows in this table.@return the number of rows in this table.

public public public public intintintint getRowCountgetRowCountgetRowCountgetRowCount() {() {() {() {

return return return return rockets.lengthrockets.lengthrockets.lengthrockets.length;;;;

}}}}

Page 44: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova44

// @// @// @// @paramparamparamparam row which row is interestingrow which row is interestingrow which row is interestingrow which row is interesting

// @// @// @// @paramparamparamparam colcolcolcol which column is interestingwhich column is interestingwhich column is interestingwhich column is interesting

// @return the value at the indicated row and column.// @return the value at the indicated row and column.// @return the value at the indicated row and column.// @return the value at the indicated row and column.

public Object public Object public Object public Object getValueAt(intgetValueAt(intgetValueAt(intgetValueAt(int row, row, row, row, intintintint colcolcolcol) {) {) {) {

switch (switch (switch (switch (colcolcolcol) {) {) {) {

case 0:case 0:case 0:case 0:

return return return return rockets[row].getNamerockets[row].getNamerockets[row].getNamerockets[row].getName();();();();

case 1:case 1:case 1:case 1:

return return return return rockets[row].getPricerockets[row].getPricerockets[row].getPricerockets[row].getPrice();();();();

case 2:case 2:case 2:case 2:

return new return new return new return new Double(rockets[row].getApogeeDouble(rockets[row].getApogeeDouble(rockets[row].getApogeeDouble(rockets[row].getApogee());());());());

default:default:default:default:

return null;return null;return null;return null;

} } } }

} } } }

}}}}

Page 45: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova45

public public public public classclassclassclass ShowRocketTableShowRocketTableShowRocketTableShowRocketTable { { { {

public static public static public static public static voidvoidvoidvoid mainmainmainmain((((StringStringStringString[] [] [] [] argsargsargsargs) {) {) {) {

setFontssetFontssetFontssetFonts();();();();

JTableJTableJTableJTable table = table = table = table = newnewnewnew JTableJTableJTableJTable((((getRocketTablegetRocketTablegetRocketTablegetRocketTable());());());());

table.table.table.table.setRowHeightsetRowHeightsetRowHeightsetRowHeight(36);(36);(36);(36);

JScrollPaneJScrollPaneJScrollPaneJScrollPane pane = pane = pane = pane = newnewnewnew JScrollPaneJScrollPaneJScrollPaneJScrollPane(table);(table);(table);(table);

pane.pane.pane.pane.setPreferredSizesetPreferredSizesetPreferredSizesetPreferredSize((((newnewnewnew javajavajavajava....awtawtawtawt....DimensionDimensionDimensionDimension(300, 100));(300, 100));(300, 100));(300, 100));

display(pane, " display(pane, " display(pane, " display(pane, " RocketsRocketsRocketsRockets");");");");

}}}}

/**/**/**/**

* Display a Swing * Display a Swing * Display a Swing * Display a Swing componentcomponentcomponentcomponent. . . . WeWeWeWe''''llllllll refactorrefactorrefactorrefactor thisthisthisthis laterlaterlaterlater intointointointo a nice a nice a nice a nice facadefacadefacadefacade....

* * * *

* @* @* @* @paramparamparamparam c c c c thethethethe componentcomponentcomponentcomponent to displayto displayto displayto display

* @* @* @* @paramparamparamparam titletitletitletitle thethethethe windowwindowwindowwindow titletitletitletitle

*/*/*/*/

public static public static public static public static voidvoidvoidvoid display(display(display(display(ComponentComponentComponentComponent c, c, c, c, StringStringStringString titletitletitletitle) {) {) {) {

JFrameJFrameJFrameJFrame frameframeframeframe = = = = newnewnewnew JFrameJFrameJFrameJFrame((((titletitletitletitle););););

frameframeframeframe....getContentPanegetContentPanegetContentPanegetContentPane().().().().addaddaddadd(c);(c);(c);(c);

frameframeframeframe....setDefaultCloseOperationsetDefaultCloseOperationsetDefaultCloseOperationsetDefaultCloseOperation((((JFrameJFrameJFrameJFrame.EXIT_ON_CLOSE); .EXIT_ON_CLOSE); .EXIT_ON_CLOSE); .EXIT_ON_CLOSE);

frameframeframeframe....packpackpackpack();();();();

frameframeframeframe....setVisiblesetVisiblesetVisiblesetVisible((((truetruetruetrue););););

}}}}

Page 46: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova46

privateprivateprivateprivate static static static static RocketTableModelRocketTableModelRocketTableModelRocketTableModel getRocketTablegetRocketTablegetRocketTablegetRocketTable() {() {() {() {

RocketRocketRocketRocket r1 = r1 = r1 = r1 = newnewnewnew RocketRocketRocketRocket("("("("ShooterShooterShooterShooter", 1.0, ", 1.0, ", 1.0, ", 1.0, newnewnewnew DollarsDollarsDollarsDollars(3.95), 50.0, 4.5);(3.95), 50.0, 4.5);(3.95), 50.0, 4.5);(3.95), 50.0, 4.5);

RocketRocketRocketRocket r2 = r2 = r2 = r2 = newnewnewnew RocketRocketRocketRocket("Orbit", 2.0, ("Orbit", 2.0, ("Orbit", 2.0, ("Orbit", 2.0, newnewnewnew DollarsDollarsDollarsDollars(29.03), 5000, 3.2);(29.03), 5000, 3.2);(29.03), 5000, 3.2);(29.03), 5000, 3.2);

returnreturnreturnreturn newnewnewnew RocketTableModelRocketTableModelRocketTableModelRocketTableModel((((newnewnewnew RocketRocketRocketRocket[] { r1, r2 });[] { r1, r2 });[] { r1, r2 });[] { r1, r2 });

}}}}

privateprivateprivateprivate static static static static voidvoidvoidvoid setFontssetFontssetFontssetFonts() {() {() {() {

Font Font Font Font fontfontfontfont = = = = newnewnewnew Font("Dialog", Font.PLAIN, 18);Font("Dialog", Font.PLAIN, 18);Font("Dialog", Font.PLAIN, 18);Font("Dialog", Font.PLAIN, 18);

UIManagerUIManagerUIManagerUIManager.put("Table.font", font);.put("Table.font", font);.put("Table.font", font);.put("Table.font", font);

UIManagerUIManagerUIManagerUIManager.put(".put(".put(".put("TableHeaderTableHeaderTableHeaderTableHeader.font", font);.font", font);.font", font);.font", font);

}}}}

}}}}

Page 47: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

47

Shrnutí

• Vzor Adapter umožňuje, aby existující třída splnila požadavky třídy Klient.

• Pokud klient specifikuje požadavky v rozhraní, vytvoří se nová třída (adapter), která implementuje požadavky rozhraní a zároveň je podtřídou existující třídy – Class Adapter

• Pokud klient nespecifikuje své požadavky přes rozhraní, vytvoří se podtřída od klienta, jejímždatovým atributem bude instance existující třídy –Object Adapter.

Page 48: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

48

Shrnutí

• Komponenta JTable s balíčku javax.swing využívávzor Adapter.

• Adapter se většinou vytvoří jako podtřída od AbstractTableModel

Page 49: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

49

Metoda Factory

• Kontext:

• při vytváření třídy obyčejně doplníme konstruktory na tvorbu instancí

• někdy klient potřebuje nový objekt, ale neví, od které z několika možných tříd vytvořit instanci (hierarchie)

• Řešení:

• metoda Factory umožňuje tvůrci tříd definovat rozhraní pro vytvářený objekt, zatímco si ponechává volbu, ze které třídy instanci vytvoří

Page 50: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

50

Klasický p říklad použití: Iterátor

• Vzor Iterátor poskytuje způsob zpřístupnit sekvenčně prvky kolekce

• Při vytváření instancí Iterátorů je použita metoda Factory

• V rozhraní Collection je metoda iterator(), kterou pak implementují všechny třídy kolekcí. Metoda iterator() izoluje toho, kdo ji volá od povědomí, od které vlastně třídy vytváří instanci.

Page 51: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova51

public public public public classclassclassclass ShowIteratorShowIteratorShowIteratorShowIterator {{{{

public static public static public static public static voidvoidvoidvoid mainmainmainmain((((StringStringStringString[] [] [] [] argsargsargsargs) {) {) {) {

List List List List listlistlistlist = = = = ArraysArraysArraysArrays....asListasListasListasList((((

newnewnewnew StringStringStringString[] { "[] { "[] { "[] { "fountainfountainfountainfountain", "", "", "", "rocketrocketrocketrocket", "", "", "", "sparklersparklersparklersparkler" });" });" });" });

IteratorIteratorIteratorIterator iteriteriteriter = list.= list.= list.= list.iteratoriteratoriteratoriterator();();();();

whilewhilewhilewhile ((((iteriteriteriter....hasNexthasNexthasNexthasNext()) ()) ()) ())

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln((((iteriteriteriter....nextnextnextnext());());());());

// // // // UncommentUncommentUncommentUncomment thethethethe nextnextnextnext line to line to line to line to seeseeseesee thethethethe iteratoriteratoriteratoriterator's 's 's 's actualactualactualactual classclassclassclass::::

// // // // SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln((((iteriteriteriter....getClassgetClassgetClassgetClass().().().().getNamegetNamegetNamegetName());());());());

}}}}

}}}}

Page 52: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

52

Rozpoznání Metody Factory

• mylná domněnka, že každá metoda která vytváří a vrací objekt je metoda „factory“

• v OOP je běžné, že metody vrací nový objekt• fakt, že metoda vytváří nový objekt nemusí

znamenat, že je příkladem metody Factory• metoda Factory je metoda, která jednak vytváří

nový objekt a dále izoluje klienta od povědomí, od které třídy vytváří objekt

• při požadavku na objekt, je definitivní třída objektu, který bude vytvořen závislá na chováníobjektu Factory, který dostal požadavek na vytvoření nového objektu

Page 53: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

53

Řízení vytvá ření instancí

• standardní cesta vytvoření instance – konstruktor

• někdy klient, který chce objekt přesně neví od které třídy se má objekt vytvořit

• např. iterátor – objekt iterátoru závisí na typu třídy, kterou chce klient procházet

Page 54: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

54

Jednoduchá statická metoda factory

• Metoda factory přijímá argument, podle kterého určí typ objektu nadtřídy Shape.

• Předávaný argument je typu String – může být i jiný typ

• V případě přidání další podtřídy – nutno změnit kód metody factory

• Konstruktory podtříd nadtřídy Shape mají přístup v rámci paketu, takže jsou přistupni i pro metodu factory(), avšak nejsou přístupni z vnějšku paketu (balíčku)

Page 55: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

55

Jednoduchá statická metoda factory

• Výsledek – kód se mění pouze v jednom místě

Page 56: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova56

// // // // jednoduchajednoduchajednoduchajednoducha statickastatickastatickastaticka metoda metoda metoda metoda factoryfactoryfactoryfactory

packagepackagepackagepackage factoryfactoryfactoryfactory.shape1;.shape1;.shape1;.shape1;

import import import import javajavajavajava....utilutilutilutil.*;.*;.*;.*;

import import import import junitjunitjunitjunit....frameworkframeworkframeworkframework.*;.*;.*;.*;

abstractabstractabstractabstract classclassclassclass ShapeShapeShapeShape {{{{

public public public public abstractabstractabstractabstract voidvoidvoidvoid drawdrawdrawdraw();();();();

public public public public abstractabstractabstractabstract voidvoidvoidvoid eraseeraseeraseerase();();();();

public static public static public static public static ShapeShapeShapeShape factoryfactoryfactoryfactory((((StringStringStringString type)type)type)type) {{{{

ifififif(type.(type.(type.(type.equalsequalsequalsequals("("("("CircleCircleCircleCircle")) ")) ")) ")) returnreturnreturnreturn newnewnewnew CircleCircleCircleCircle();();();();

ifififif(type.(type.(type.(type.equalsequalsequalsequals("Square")) ("Square")) ("Square")) ("Square")) returnreturnreturnreturn newnewnewnew Square();Square();Square();Square();

throwthrowthrowthrow newnewnewnew RuntimeExceptionRuntimeExceptionRuntimeExceptionRuntimeException((((

""""BadBadBadBad shapeshapeshapeshape creationcreationcreationcreation: " + type);: " + type);: " + type);: " + type);

}}}}

}}}}

classclassclassclass CircleCircleCircleCircle extendsextendsextendsextends ShapeShapeShapeShape {{{{

CircleCircleCircleCircle() {} () {} () {} () {} // // // // PackagePackagePackagePackage----accessaccessaccessaccess constructorconstructorconstructorconstructor

public public public public voidvoidvoidvoid drawdrawdrawdraw() { () { () { () {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("("("("CircleCircleCircleCircle....drawdrawdrawdraw"); "); "); ");

}}}}

public public public public voidvoidvoidvoid eraseeraseeraseerase() { () { () { () {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("("("("CircleCircleCircleCircle....eraseeraseeraseerase"); "); "); ");

}}}}

}}}}

Page 57: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova57

classclassclassclass Square Square Square Square extendsextendsextendsextends ShapeShapeShapeShape {{{{

Square() {} Square() {} Square() {} Square() {} // // // // PackagePackagePackagePackage----accessaccessaccessaccess constructorconstructorconstructorconstructor

public public public public voidvoidvoidvoid drawdrawdrawdraw() { () { () { () {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("Square.("Square.("Square.("Square.drawdrawdrawdraw"); "); "); ");

}}}}

public public public public voidvoidvoidvoid eraseeraseeraseerase() { () { () { () {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("Square.("Square.("Square.("Square.eraseeraseeraseerase"); "); "); ");

}}}}

}}}}

public public public public classclassclassclass ShapeFactory1 ShapeFactory1 ShapeFactory1 ShapeFactory1 extendsextendsextendsextends TestCaseTestCaseTestCaseTestCase {{{{

StringStringStringString shlistshlistshlistshlist[] = { "[] = { "[] = { "[] = { "CircleCircleCircleCircle", "Square", ", "Square", ", "Square", ", "Square",

"Square", ""Square", ""Square", ""Square", "CircleCircleCircleCircle", "", "", "", "CircleCircleCircleCircle", "Square" };", "Square" };", "Square" };", "Square" };

List List List List shapesshapesshapesshapes = = = = newnewnewnew ArrayListArrayListArrayListArrayList();();();();

public public public public voidvoidvoidvoid test() {test() {test() {test() {

IteratorIteratorIteratorIterator itititit = = = = ArraysArraysArraysArrays....asListasListasListasList((((shlistshlistshlistshlist).).).).iteratoriteratoriteratoriterator();();();();

whilewhilewhilewhile((((itititit....hasNexthasNexthasNexthasNext())())())())

shapesshapesshapesshapes....addaddaddadd((((ShapeShapeShapeShape....factoryfactoryfactoryfactory((((((((StringStringStringString))))itititit....nextnextnextnext()));()));()));()));

itititit = = = = shapesshapesshapesshapes....iteratoriteratoriteratoriterator();();();();

whilewhilewhilewhile((((itititit....hasNexthasNexthasNexthasNext()) {()) {()) {()) {

ShapeShapeShapeShape s = (s = (s = (s = (ShapeShapeShapeShape))))itititit....nextnextnextnext();();();();

s.s.s.s.drawdrawdrawdraw();();();();

s.s.s.s.eraseeraseeraseerase();();();();

}}}}

}}}}

public static public static public static public static voidvoidvoidvoid mainmainmainmain((((StringStringStringString argsargsargsargs[]) {[]) {[]) {[]) {

junitjunitjunitjunit....textuitextuitextuitextui....TestRunnerTestRunnerTestRunnerTestRunner.run(ShapeFactory1..run(ShapeFactory1..run(ShapeFactory1..run(ShapeFactory1.classclassclassclass););););

}}}}

}}}}

Page 58: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

58

Polymorfické metody factory

• Toto řešení odpovídá původním požadavkům knihy Design Patterns – odlišné třídy od metody factory() mohou být podtřídami základní metody factory()

• Předchozí případ byl speciálním případem

• V následujícím příkladě jsou metody factorymodifikovány a jsou v oddělených třídách, jako virtuální funkce.

• Podtřídy Shape jsou dynamicky nahrávány do paměti

• Třídy Factory jsou vnitřní třídy

Page 59: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

59

Polymorfické metody factory

• Metoda create() třídy ShapeFactory je protected –což znamená, že nemůže být volaná přímo, ale může být zastíněna (overriden).

• Každá z podtřídy třídy Shape musí vytvořit svoji vlastní podtřídy od FactoryShape a zastínit metodu create() proto, aby vytvořily objekt vlastního typu

• Vytvoření objektu je provedeno:ShapeFactory.createShape()

což je statická metoda používající Map a ShapeFactory

Page 60: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

60

Polymorfické metody factory

• Třída ShapeFactory musí být inicializovanánahráním Map s objekty factory – což se provádípři statické inicializaci

• Při přidání další třídy do tohoto návrhu musíte zdědit třídu vytvořenou třídou Factory a přidat statickou inicializaci k nahrávání Map

Page 61: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

61UML diagram t řídtřídy Factory jsou vno řené třídy

Page 62: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova62

// // // // PolymorphicPolymorphicPolymorphicPolymorphic factoryfactoryfactoryfactory methodsmethodsmethodsmethods....

packagepackagepackagepackage factoryfactoryfactoryfactory.shape2;.shape2;.shape2;.shape2;

import import import import javajavajavajava....utilutilutilutil.*;.*;.*;.*;

import import import import junitjunitjunitjunit....frameworkframeworkframeworkframework.*;.*;.*;.*;

interface interface interface interface ShapeShapeShapeShape {{{{

voidvoidvoidvoid drawdrawdrawdraw();();();();

voidvoidvoidvoid eraseeraseeraseerase();();();();

}}}}

abstractabstractabstractabstract classclassclassclass ShapeFactoryShapeFactoryShapeFactoryShapeFactory {{{{

protectedprotectedprotectedprotected abstractabstractabstractabstract ShapeShapeShapeShape createcreatecreatecreate();();();();

privateprivateprivateprivate static Map <static Map <static Map <static Map <StringStringStringString, , , , ShapeFactoryShapeFactoryShapeFactoryShapeFactory>>>>factoriesfactoriesfactoriesfactories = = = =

newnewnewnew HashMapHashMapHashMapHashMap<<<<StringStringStringString, , , , ShapeFactoryShapeFactoryShapeFactoryShapeFactory>();>();>();>();

public static public static public static public static voidvoidvoidvoid

addFactoryaddFactoryaddFactoryaddFactory((((StringStringStringString id, id, id, id, ShapeFactoryShapeFactoryShapeFactoryShapeFactory f) {f) {f) {f) {

factoriesfactoriesfactoriesfactories.put(id, f);.put(id, f);.put(id, f);.put(id, f);

}}}}

Page 63: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova63

// A // A // A // A TemplateTemplateTemplateTemplate MethodMethodMethodMethod::::

public static public static public static public static finalfinalfinalfinal

ShapeShapeShapeShape createShapecreateShapecreateShapecreateShape((((StringStringStringString id) {id) {id) {id) {

ifififif(!(!(!(!factoriesfactoriesfactoriesfactories....containsKeycontainsKeycontainsKeycontainsKey(id)) {(id)) {(id)) {(id)) {

trytrytrytry {{{{

// // // // LoadLoadLoadLoad dynamicallydynamicallydynamicallydynamically

ClassClassClassClass....forNameforNameforNameforName("("("("factoryfactoryfactoryfactory.shape2." + id);.shape2." + id);.shape2." + id);.shape2." + id);

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("Konec ("Konec ("Konec ("Konec trytrytrytry");");");");

} } } } catchcatchcatchcatch((((ClassNotFoundExceptionClassNotFoundExceptionClassNotFoundExceptionClassNotFoundException e) {e) {e) {e) {

throwthrowthrowthrow newnewnewnew RuntimeExceptionRuntimeExceptionRuntimeExceptionRuntimeException((((

""""BadBadBadBad shapeshapeshapeshape creationcreationcreationcreation: " + id);: " + id);: " + id);: " + id);

}}}}

// // // // SeeSeeSeeSee ifififif itititit waswaswaswas put in:put in:put in:put in:

ifififif(!(!(!(!factoriesfactoriesfactoriesfactories....containsKeycontainsKeycontainsKeycontainsKey(id))(id))(id))(id))

throwthrowthrowthrow newnewnewnew RuntimeExceptionRuntimeExceptionRuntimeExceptionRuntimeException((((

""""BadBadBadBad shapeshapeshapeshape creationcreationcreationcreation: " + id);: " + id);: " + id);: " + id);

}}}}

returnreturnreturnreturn

((((factoriesfactoriesfactoriesfactories....getgetgetget(id)).(id)).(id)).(id)).createcreatecreatecreate();();();();

}}}}

}}}}

Page 64: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova64

classclassclassclass CircleCircleCircleCircle implementsimplementsimplementsimplements ShapeShapeShapeShape {{{{

privateprivateprivateprivate CircleCircleCircleCircle() {}() {}() {}() {}

public public public public voidvoidvoidvoid drawdrawdrawdraw() { () { () { () {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("("("("CircleCircleCircleCircle....drawdrawdrawdraw"); "); "); ");

}}}}

public public public public voidvoidvoidvoid eraseeraseeraseerase() { () { () { () {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("("("("CircleCircleCircleCircle....eraseeraseeraseerase");");");");

}}}}

privateprivateprivateprivate static static static static classclassclassclass FactoryFactoryFactoryFactory

extendsextendsextendsextends ShapeFactoryShapeFactoryShapeFactoryShapeFactory {{{{

protectedprotectedprotectedprotected ShapeShapeShapeShape createcreatecreatecreate() { () { () { () {

returnreturnreturnreturn newnewnewnew CircleCircleCircleCircle(); (); (); ();

}}}}

}}}}

static {static {static {static {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("Kruh");("Kruh");("Kruh");("Kruh");

ShapeFactoryShapeFactoryShapeFactoryShapeFactory....addFactoryaddFactoryaddFactoryaddFactory((((

""""CircleCircleCircleCircle", ", ", ", newnewnewnew FactoryFactoryFactoryFactory());());());());

}}}}

}}}}

Page 65: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova65

classclassclassclass Square Square Square Square implementsimplementsimplementsimplements ShapeShapeShapeShape {{{{

privateprivateprivateprivate Square() {} Square() {} Square() {} Square() {}

public public public public voidvoidvoidvoid drawdrawdrawdraw() { () { () { () {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("Square.("Square.("Square.("Square.drawdrawdrawdraw"); "); "); ");

}}}}

public public public public voidvoidvoidvoid eraseeraseeraseerase() { () { () { () {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("Square.("Square.("Square.("Square.eraseeraseeraseerase"); "); "); ");

}}}}

privateprivateprivateprivate static static static static classclassclassclass FactoryFactoryFactoryFactory

extendsextendsextendsextends ShapeFactoryShapeFactoryShapeFactoryShapeFactory {{{{

protectedprotectedprotectedprotected ShapeShapeShapeShape createcreatecreatecreate() { () { () { () {

returnreturnreturnreturn newnewnewnew Square(); Square(); Square(); Square();

}}}}

}}}}

static {static {static {static {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("("("("CtverecCtverecCtverecCtverec");");");");

ShapeFactoryShapeFactoryShapeFactoryShapeFactory....addFactoryaddFactoryaddFactoryaddFactory((((

"Square", "Square", "Square", "Square", newnewnewnew FactoryFactoryFactoryFactory());());());());

}}}}

}}}}

Page 66: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova66

public public public public classclassclassclass ShapeFactory2 ShapeFactory2 ShapeFactory2 ShapeFactory2 extendsextendsextendsextends TestCaseTestCaseTestCaseTestCase {{{{

StringStringStringString shlistshlistshlistshlist[] = { "[] = { "[] = { "[] = { "CircleCircleCircleCircle", "Square", ", "Square", ", "Square", ", "Square",

"Square", ""Square", ""Square", ""Square", "CircleCircleCircleCircle", "", "", "", "CircleCircleCircleCircle", "Square" };", "Square" };", "Square" };", "Square" };

List<List<List<List<ShapeShapeShapeShape> > > > shapesshapesshapesshapes = = = = newnewnewnew ArrayListArrayListArrayListArrayList<<<<ShapeShapeShapeShape>();>();>();>();

public public public public voidvoidvoidvoid test() {test() {test() {test() {

// // // // ThisThisThisThis justjustjustjust makesmakesmakesmakes suresuresuresure itititit willwillwillwill completecompletecompletecomplete

// // // // withoutwithoutwithoutwithout throwingthrowingthrowingthrowing anananan exceptionexceptionexceptionexception....

IteratorIteratorIteratorIterator itititit = = = = ArraysArraysArraysArrays....asListasListasListasList((((shlistshlistshlistshlist).).).).iteratoriteratoriteratoriterator();();();();

whilewhilewhilewhile((((itititit....hasNexthasNexthasNexthasNext())())())())

shapesshapesshapesshapes....addaddaddadd((((

ShapeFactoryShapeFactoryShapeFactoryShapeFactory....createShapecreateShapecreateShapecreateShape((((((((StringStringStringString)()()()(itititit....nextnextnextnext())));())));())));())));

itititit = = = = shapesshapesshapesshapes....iteratoriteratoriteratoriterator();();();();

whilewhilewhilewhile((((itititit....hasNexthasNexthasNexthasNext()) {()) {()) {()) {

ShapeShapeShapeShape s = (s = (s = (s = (ShapeShapeShapeShape))))itititit....nextnextnextnext();();();();

s.s.s.s.drawdrawdrawdraw();();();();

s.s.s.s.eraseeraseeraseerase();();();();

}}}}

}}}}

public static public static public static public static voidvoidvoidvoid mainmainmainmain((((StringStringStringString argsargsargsargs[]) {[]) {[]) {[]) {

junitjunitjunitjunit....textuitextuitextuitextui....TestRunnerTestRunnerTestRunnerTestRunner.run(ShapeFactory2..run(ShapeFactory2..run(ShapeFactory2..run(ShapeFactory2.classclassclassclass););););

}}}}

}}}}

Page 67: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

67

Abstract Factory

• Někdy chcete vytvořit objekt, zatím ale není jasnéod které třídy

• v tomto případěmožno použít vzor metoda Factory s metodou, která používá vnější faktor, který řídí, od které třídy se vytvoří instance

• Smyslem tohoto vzoru je dovolit vytvoření rodiny souvisejících nebo závislých objektů, přičemžklient je izolován od volání těchto tříd.

Page 68: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

68

Abstract Factory

• Vzor Abstract Factory je podobný objektům Factory s předchozího příkladu, ale s více factory() metodami.

• Každá z těchto factory metod vytváří odlišný typ objektu.

• Myšlenka je, že v době tvorby objektu Factoryrozhodnete, jak tyto objekty vytvořené Factorypoužijete.

Page 69: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

69

Abstract Factory

• V následujícím příkladu existují rozhraníPlayera Obstacle ale s různými typy Players a Obstacles (třídy implementující rozhraní) závisléna tom, kterou hru hrajete.

• Vy rozhodnete o výběru hry výběrem konkrétníGameElementFactory a potéGameEnvironmentřídí nastavení a hraní hry.

• V příkladu jsou nastavení a vlastní hra velmi jednoduché, avšak úvodní podmínky a změny stavů mohou určit mnoho ze závěru hry.

Page 70: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

70

Abstract Factory

• Třída GameEnvironment není navržena k dědění, ačkoli by to dávalo smysl.

Page 71: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

71Abstract FactoryUML diagram t říd

Page 72: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova72

interface interface interface interface ObstacleObstacleObstacleObstacle {{{{

voidvoidvoidvoid actionactionactionaction();();();();

}}}}

interface interface interface interface PlayerPlayerPlayerPlayer {{{{

voidvoidvoidvoid interactWithinteractWithinteractWithinteractWith((((ObstacleObstacleObstacleObstacle o);o);o);o);

}}}}

classclassclassclass KittyKittyKittyKitty implementsimplementsimplementsimplements PlayerPlayerPlayerPlayer {{{{

public public public public voidvoidvoidvoid interactWithinteractWithinteractWithinteractWith((((ObstacleObstacleObstacleObstacle ob) {ob) {ob) {ob) {

SystemSystemSystemSystem....outoutoutout....printprintprintprint("("("("KittyKittyKittyKitty has has has has encounteredencounteredencounteredencountered a ");a ");a ");a ");

ob.ob.ob.ob.actionactionactionaction();();();();

}}}}

}}}}

classclassclassclass KungFuGuyKungFuGuyKungFuGuyKungFuGuy implementsimplementsimplementsimplements PlayerPlayerPlayerPlayer {{{{

public public public public voidvoidvoidvoid interactWithinteractWithinteractWithinteractWith((((ObstacleObstacleObstacleObstacle ob) {ob) {ob) {ob) {

SystemSystemSystemSystem....outoutoutout....printprintprintprint("("("("KungFuGuyKungFuGuyKungFuGuyKungFuGuy nownownownow battlesbattlesbattlesbattles a ");a ");a ");a ");

ob.ob.ob.ob.actionactionactionaction();();();();

}}}}

}}}}

classclassclassclass PuzzlePuzzlePuzzlePuzzle implementsimplementsimplementsimplements ObstacleObstacleObstacleObstacle {{{{

public public public public voidvoidvoidvoid actionactionactionaction() { () { () { () {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("("("("PuzzlePuzzlePuzzlePuzzle"); "); "); ");

}}}}

}}}}

Page 73: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova73

classclassclassclass NastyWeaponNastyWeaponNastyWeaponNastyWeapon implementsimplementsimplementsimplements ObstacleObstacleObstacleObstacle {{{{

public public public public voidvoidvoidvoid actionactionactionaction() { () { () { () {

SystemSystemSystemSystem....outoutoutout....printlnprintlnprintlnprintln("("("("NastyWeaponNastyWeaponNastyWeaponNastyWeapon"); "); "); ");

}}}}

}}}}

// // // // TheTheTheThe AbstractAbstractAbstractAbstract FactoryFactoryFactoryFactory::::

interface interface interface interface GameElementFactoryGameElementFactoryGameElementFactoryGameElementFactory {{{{

PlayerPlayerPlayerPlayer makePlayermakePlayermakePlayermakePlayer();();();();

ObstacleObstacleObstacleObstacle makeObstaclemakeObstaclemakeObstaclemakeObstacle();();();();

}}}}

// // // // ConcreteConcreteConcreteConcrete factoriesfactoriesfactoriesfactories::::

classclassclassclass KittiesAndPuzzlesKittiesAndPuzzlesKittiesAndPuzzlesKittiesAndPuzzles

implementsimplementsimplementsimplements GameElementFactoryGameElementFactoryGameElementFactoryGameElementFactory {{{{

public public public public PlayerPlayerPlayerPlayer makePlayermakePlayermakePlayermakePlayer() { () { () { () {

returnreturnreturnreturn newnewnewnew KittyKittyKittyKitty();();();();

}}}}

public public public public ObstacleObstacleObstacleObstacle makeObstaclemakeObstaclemakeObstaclemakeObstacle() {() {() {() {

returnreturnreturnreturn newnewnewnew PuzzlePuzzlePuzzlePuzzle();();();();

}}}}

}}}}

classclassclassclass KillAndDismemberKillAndDismemberKillAndDismemberKillAndDismember

implementsimplementsimplementsimplements GameElementFactoryGameElementFactoryGameElementFactoryGameElementFactory {{{{

public public public public PlayerPlayerPlayerPlayer makePlayermakePlayermakePlayermakePlayer() { () { () { () {

returnreturnreturnreturn newnewnewnew KungFuGuyKungFuGuyKungFuGuyKungFuGuy();();();();

}}}}

public public public public ObstacleObstacleObstacleObstacle makeObstaclemakeObstaclemakeObstaclemakeObstacle() {() {() {() {

returnreturnreturnreturn newnewnewnew NastyWeaponNastyWeaponNastyWeaponNastyWeapon();();();();

}}}}

}}}}

Page 74: Návrhové vzory 2 Command, Observer, Adapter, Factory ...hunka/vyuka/javaOOP/obop2/jvcv10/Vzory_2.pdf · 3 Command - kontext • Klient, který využívá služeb (metod) objektu

Osnova74

classclassclassclass GameEnvironmentGameEnvironmentGameEnvironmentGameEnvironment {{{{

privateprivateprivateprivate GameElementFactoryGameElementFactoryGameElementFactoryGameElementFactory gefgefgefgef;;;;

privateprivateprivateprivate PlayerPlayerPlayerPlayer p;p;p;p;

privateprivateprivateprivate ObstacleObstacleObstacleObstacle ob;ob;ob;ob;

public public public public GameEnvironmentGameEnvironmentGameEnvironmentGameEnvironment((((

GameElementFactoryGameElementFactoryGameElementFactoryGameElementFactory factoryfactoryfactoryfactory) {) {) {) {

gefgefgefgef = = = = factoryfactoryfactoryfactory;;;;

p = p = p = p = factoryfactoryfactoryfactory....makePlayermakePlayermakePlayermakePlayer(); (); (); ();

ob = ob = ob = ob = factoryfactoryfactoryfactory....makeObstaclemakeObstaclemakeObstaclemakeObstacle();();();();

}}}}

public public public public voidvoidvoidvoid playplayplayplay() { p.() { p.() { p.() { p.interactWithinteractWithinteractWithinteractWith(ob); }(ob); }(ob); }(ob); }

}}}}

public public public public classclassclassclass GamesGamesGamesGames {{{{

public static public static public static public static voidvoidvoidvoid mainmainmainmain((((StringStringStringString argsargsargsargs[]) {[]) {[]) {[]) {

GameElementFactoryGameElementFactoryGameElementFactoryGameElementFactory

kpkpkpkp = = = = newnewnewnew KittiesAndPuzzlesKittiesAndPuzzlesKittiesAndPuzzlesKittiesAndPuzzles(),(),(),(),

kdkdkdkd = = = = newnewnewnew KillAndDismemberKillAndDismemberKillAndDismemberKillAndDismember();();();();

GameEnvironmentGameEnvironmentGameEnvironmentGameEnvironment

g1 = g1 = g1 = g1 = newnewnewnew GameEnvironmentGameEnvironmentGameEnvironmentGameEnvironment((((kpkpkpkp), ), ), ), // // // // vnejsivnejsivnejsivnejsi parametrparametrparametrparametr

g2 = g2 = g2 = g2 = newnewnewnew GameEnvironmentGameEnvironmentGameEnvironmentGameEnvironment((((kdkdkdkd);););); // // // // vnejsivnejsivnejsivnejsi parametrparametrparametrparametr

g1.g1.g1.g1.playplayplayplay();();();();

g2.g2.g2.g2.playplayplayplay();();();();

}}}}

} } } }