Prezentace se nahrává, počkejte prosím

Prezentace se nahrává, počkejte prosím

Vaše jistota na trhu IT Rozhraní Rudolf Pecinovský

Podobné prezentace


Prezentace na téma: "Vaše jistota na trhu IT Rozhraní Rudolf Pecinovský"— Transkript prezentace:

1 Vaše jistota na trhu IT Rozhraní Rudolf Pecinovský

2 Vaše jistota na trhu IT Obsah s odkazy ►Rozhraní × ImplementaceRozhraní × Implementace ►Interface a jeho implementaceInterface a jeho implementace ►Návrhový vzor SlužebníkNávrhový vzor Služebník ►Návrhový vzor ProstředníkNávrhový vzor Prostředník ►Návrhový vzor Pozorovatel / PosluchačNávrhový vzor Pozorovatel / Posluchač ►Návrhový vzor MostNávrhový vzor Most ►BalíčkyBalíčky

3 Vaše jistota na trhu IT Rozhraní × Implementace ►Rozhraní × Implementace ►Signatura × Kontrakt ►Dokumentační komentáře ►Zásady správného programování 159–176

4 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 4 Trocha mytologie ►Janus římský bůh vchodů, dveří, počátku a konce ►Měl dvě tváře: jedna hleděla do budoucnosti, druhá do minulosti ►I program má dvě tváře: Rozhraní × Implementace

5 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 5 RozhraníImplementace Definuje, co bude zbytek programu o dané entitě vědět Všem na sebe všechno řekne Zabezpečuje, aby entita plnila svoji funkci Všechno se snaží maximálně utajit I samotné rozhraní má dvě složky ►Signatura Specifikuje vlastnosti, které může zkontrolovat překladač (názvy, typy, …) ►Kontrakt Doplňuje další důležité informace, které však překladač zkontrolovat nedokáže – o jejich dodržení se musí postarat programátor

6 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 6 Rozhraní a implementace metody ►Rozhraní – signatura ● Jmenuje se blikni ● Nemá žádné parametry ● Nic nevrací ►Rozhraní – kontrakt ● Světlo nejprve „rozsvítí“ ● Nechá je „svítit“ půl vteřiny ● Po půl vteřině je opět „zhasne“ ►Implementace ● K rozsvícení světla používá svoji metodu rozsviť() ● Půlvteřinové svícení zabezpečí pozastavením programu pomocí metody čekej() třídy IO, které předá počet milisekund čekání ● Zhasnutí realizuje zavoláním své metody zhasni() public void blikni() { rozsviť(); IO.čekej( 500 ); zhasni(); }

7 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 7 ►Rozhraní – signatura ● Třída se jmenuje Světlo ● Třída má metody – 4 přetížené verze konstruktorů – rozsviť(), zhasni() – blikni() – getBarva(), getPozice() – getPrůměr(), isZhasnuté() – setPozice(int,int) – setPozice(Pozice) ►Rozhraní – kontrakt ● Co která metoda umí ►Implementace ● Používané atributy ● Realizace jednotlivých metod public class Světlo { private static final Barva ZHASNUTÁ = Barva.ČERNÁ; private final Elipsa žárovka; private final Barva barva; public Světlo() { this( 0, 0 ); } public Světlo( int x, int y ) { this( x, y, Barva.ČERVENÁ ); } public Světlo( int x, int y, Barva barva ) { this( x, y, 50, barva ); } public Světlo( int x, int y, int průměr, Barva barva ) { žárovka = new Elipsa( x, y, průměr, průměr, barva ); this.barva = barva; } public void zhasni() { žárovka.setBarva( ZHASNUTÁ ); } public void rozsviť() { žárovka.setBarva( barva ); } public void blikni() { rozsviť(); IO.čekej( 500 ); zhasni(); } public int getPrůměr() { return žárovka.getŠířka(); } public Barva getBarva() { return barva; } public boolean isZhasnuté() { return žárovka.getBarva() == ZHASNUTÁ; } public Pozice getPozice() { return new Pozice( žárovka.getX(), žárovka.getY() ); } public void setPozice( int x, int y ) { žárovka.setPozice( x, y ); } public void setPozice( Pozice p) { žárovka.setPozice( p.x, p.y ); } Rozhraní a implementace třídy

8 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 8 Kontrakt = dokumentační komentáře ►Nejlepší způsob, jak můžeme specifikovat kontrakt, je podrobně jej vypsat v dokumentačním komentáři ►Dokumentační komentář je součástí syntaxe Javy ● Začíná /** a končí */ (otevírací a zavírací komentářová závorka) ● Umisťuje se vždy před dokumentovanou entitu (třídu, metodu, atribut) ● Publikuje se ve formátu HTML, je v něm možno použít HTML značky (tagy) ● Může obsahovat speciální vlastní značky s předem definovaným významem ● Bývá zvykem začínat pokračovací řádky ve zdrojovém kódu hvězdičkou ►Součástí JDK je program javadoc.exe, který z dokumentačních komentářů vyrobí profesionální dokumentaci ►Dokumentace k API standardní knihovny je vyrobena právě tímto způsobem

9 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 9 Značky v dokumentačních komentářích ►Zde budou uvedeny jen ty nejdůležitější, zbytek v učebnicích a v dokumentaci, kterou najdete na adrese \tooldocs\windows\javadoc.html#javadoctags kde je složka, kam jste si instalovali dokumentaci ►Dokumentace třídy: –autor třídy (podepisujte své programy) –verze programu (uvádějte, budete-li program vylepšovat) ►Dokumentace metody: –význam parametru (název za značku musí být odpovídat názvu parametru v hlavičce metody) –popis toho, co metoda vrací ►Značky v textu komentáře: ● ?} –text ? bude vysazen neproporcionálním písmem ● ?} –do vytvořené dokumentace bude vložen hypertextový odkaz na ? ►Použití dokumentačních komentářů si můžete prohlédnout v projektech vystavených na webu s přednáškami

10 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 10 Vytvoření dokumentace v BlueJ ►Editor BlueJ zobrazuje ● Zdrojový kód třídy = její implementaci ● Dokumentaci třídy = její rozhraní ►Při první žádosti o zobrazení dokumentace třídy zavolá BlueJ program javadoc a nechá jej dokumentaci vytvořit ►Vytvořená dokumentace se ukládá do podsložky doc aktuálního projektu ►Příkazem Nástroje -> Dokumentace projektu je možno požádat o vytvoření dokumentace všech tříd projektu –> ta se pak otevře v implicitním prohlížeči webových stránek

11 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 11 Příklad dokumentované třídy1/2 /************************************************************** * Instance třídy Světlo} představují simulace * rozsvítitelných a zhasnutelných pohyblivých světel. * Rudolf Pecinovský 1.02 */ public class Světlo { //Barva zhasnutých světel společná pro všechny instance private static final Barva ZHASNUTÁ = Barva.ČERNÁ; private final Elipsa žárovka; //Kruh simulující dané světlo private final Barva barva; //Barva rozsvíceného světla /********************************************************** * Vytvoří světlo implicitních rozměrů a barvy * umístěné v imlicitní pozici (levý horní roh plátna). */ public Světlo() { this( 0, 0 ); } Lze použít HTML značky BlueJ barevně odlišuje běžné a dokumentační komentáře

12 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 12 Příklad dokumentované třídy2/2 /********************************************************** * Vytvoří světlo implicitních rozměrů a barvy * umístěné na zadaných souřadnicích. * x Vodorovná souřadnice vytvářeného světla y Svislá souřadnice vytvářeného světla */ public Světlo( int x, int y ) { this( x, y, Barva.ČERVENÁ ); } /********************************************************** * Vytvoří světlo implicitních rozměrů zadané barvy * umístěné na zadaných souřadnicích. * x Vodorovná souřadnice vytvářeného světla y Svislá souřadnice vytvářeného světla barva Barva rozsvíceného světla */ public Světlo( int x, int y, Barva barva ) { this( x, y, 50, barva ); }

13 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 13 Dokumentace uvedené třídy

14 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 14 Dokumentace standardní knihovny

15 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 15 Šablona standardní třídy /************************************************************ * Instance třídy Šablona} představují... * jméno autora , */ public class Šablona { //== KONSTANTNÍ ATRIBUTY TŘÍDY ============================== //== PROMĚNNÉ ATRIBUTY TŘÍDY ================================ //== KONSTANTNÍ ATRIBUTY INSTANCÍ =========================== //== PROMĚNNÉ ATRIBUTY INSTANCÍ ============================= //== PŘÍSTUPOVÉ METODY ATRIBUTŮ TŘÍDY ======================= //== OSTATNÍ NESOUKROMÉ METODY TŘÍDY ======================== //########################################################### //== KONSTRUKTORY A TOVÁRNÍ METODY ========================== //== ABSTRAKTNÍ METODY ====================================== //== PŘÍSTUPOVÉ METODY INSTANCÍ ============================= //== OSTATNÍ NESOUKROMÉ METODY INSTANCÍ ==================== //== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ======================== //== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ===================== //== VNOŘENÉ A VNITŘNÍ TŘÍDY ================================ //== TESTOVACÍ METODY A TŘÍDY =============================== }

16 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 16 Třída Světlo ve standardní šabloně /************************************************************** * Instance třídy Světlo představují simulace rozsvítitelných * a zhasnutelných pohyblivých světel. * Rudolf Pecinovský 1.02 */ public class Světlo { //== KONSTANTNÍ ATRIBUTY TŘÍDY ================================ //Barva zhasnutých světel private static final Barva ZHASNUTÁ = Barva.ČERNÁ; //== PROMĚNNÉ ATRIBUTY TŘÍDY ================================== //== KONSTANTNÍ ATRIBUTY INSTANCÍ ============================= private final Elipsa žárovka; //Kruh simulující dané světlo private final Barva barva; //Barva rozsvíceného světla //== PROMĚNNÉ ATRIBUTY INSTANCÍ =============================== //== NESOUKROMÉ METODY TŘÍDY ================================== //############################################################# //== KONSTRUKTORY A TOVÁRNÍ METODY ============================ /********************************************************** * Vytvoří světlo implicitních rozměrů a barvy * umístěné v imlicitní pozici (levý horní roh plátna). */ public Světlo() { this( 0, 0 ); } /********************************************************** * Vytvoří světlo implicitních rozměrů a barvy * umístěné na zadaných souřadnicích. * x Vodorovná souřadnice vytvářeného světla y Svislá souřadnice vytvářeného světla */ public Světlo( int x, int y ) { this( x, y, Barva.ČERVENÁ ); } /********************************************************** * Vytvoří světlo zadaných rozměrů a barvy * umístěné na zadaných souřadnicích. * x Vodorovná souřadnice vytvářeného světla y Svislá souřadnice vytvářeného světla průměr Průměr kruhu simulujícího světlo barva Barva rozsvíceného světla */ public Světlo( int x, int y, int průměr, Barva barva ) { žárovka = new Elipsa( x, y, průměr, průměr, barva ); this.barva = barva; } //== ABSTRAKTNÍ METODY ======================================== //== NESOUKROMÉ METODY INSTANCÍ ============================== /********************************************************** * Simuluje zhasnutí světla vybarvením jeho kruhu * barvou zhasnutého světla. */ public void zhasni() { žárovka.setBarva( ZHASNUTÁ ); } /********************************************************** * Simuluje rozsvícení světla vybarvením jeho kruhu * barvou rozsvíceného světla. */ public void rozsviť() { žárovka.setBarva( barva ); } //... a další, zde nezobrazené metody

17 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 17 Zásady správného programování ►Snažit se o maximální přehlednost programu Napsat program, kterému rozumí počítač, umí každý trouba. Dobří programátoři píší programy, kterým rozumí lidé. Martin Fowler, Refactoring ►Dodržovat zavedené konvence ● Jsou zveřejněné na ►Volit smysluplné identifikátory ►Odsazovat vnitřky všech bloků ►Důsledně vše komentovat ● Komentář v kódu nemá popisovat co příkaz dělá (to čtenář vidí), ale vysvětlovat co a proč příkaz/metoda/atribut dělá a proč v programu je ● Komentujte i soukromé metody a atributy

18 Vaše jistota na trhu IT Interface a jeho implementace ►Syntaktická definice ►Modifikátory public a abstract ►Instance rozhraní ►Implementace zadaného rozhraní ►Rozhraní v BlueJ ►Trocha terminologie ►Proč používat interface 260–272 75–78

19 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 19 Formalizovaný zápis rozhraní – interface ►Java zavedla speciální konstrukci umožňující deklarovat rozhraní bez jakékoliv zmínky o implementaci ►Konstrukce dostala název interface – je to vlastně třída bez implementace ►Signatura rozhraní je dána deklaracemi metod a statických konstant (konstanty se nedoporučuje používat) ►Kontrakt je (stejně jako u standardních tříd) definován prostřednictvím dokumentačních komentářů ►Také interface je třeba přeložit, po překladu má vlastní soubor.class ►V diagramu tříd je doplněn stereotypem «interface»

20 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 20 Příklad zdrojového kódu rozhraní public interface ISemafor { /** Rozsvítí oranžové světlo. */ public void pozor(); /** Rozsvítí červené světlo. */ public void stop(); /** Rozsvítí rozsvíté červené + oranžové světlo. */ public void připravit(); /** Rozsvítí zelené světlo. */ public void volno(); /** Zhasne všechna světla. */ public void nic(); /** Projde postupně celým cyklem s implicitními dobami trvání stavů. */ public void cyklus(); /** Projde postupně celým cyklem se zadanými dobami trvání stavů. pozor Doba, po níž bude svítit samotná oranžová stop Doba, po níž bude svítit samotná červená připravit Doba, po níž bude svítit červená s oranžovou volno Doba, po níž bude svítit samotná zelená */ public void cyklus( int pozor, int stop, int připravit, int volno ); } Metody nemají implementaci = tělo, jsou pouze abstraktní – místo těla mají středník

21 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 21 interface – syntaktické definice Rozhraní: [ Modifikátor_přístupu ] interface Název_rozhraní ¶ [ extends Název_rozhraní [, Název_rozhraní ] …] ¶ { [ Deklarace ]… } Deklarace: Deklarace_třídní_konstanty Deklarace_metody Definice_vnořené_třídy Deklarace_metody: [ Modifikátor ]… Typ_návratové_hodnoty ¶ Název ( [ Seznam_parametrů ] ) ;

22 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 22 Modifikátory public a abstract ►Modifikátor public ● Všechny metody deklarované rozhraním jsou povinně public ● Protože rozhraní neveřejné metody mít stejně nemůže, povoluje syntaxe modifikátor public nepsat ● Implementující třídy jej však u svých metod uvádět musí => doporučuji jej psát – pak se dá z rozhraní snáze kopírovat ►Modifikátor abstract ● Všechny metody deklarované rozhraním jsou abstraktní (jsou to pouze deklarace bez implementace) ● Kdybychom takovou metodu deklarovali ve třídě, museli bychom u ní uvést modifikátor abstract ● Protože rozhraní konkrétní (tj. implementované) metody mít stejně nemůže, povoluje syntaxe modifikátor abstract nepsat ● Implementující třídy jej musí své metody implementovat => nebudou abstraktní => doporučuji neuvádět modifikátor abstract ani v rozhraní – pak se dá z rozhraní snáze kopírovat

23 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 23 Rozhraní a jeho instance ►Rozhraní ( interface ) nemá žádnou implementaci => nemůže mít ani vlastní instance ● Instance se musí vyrobit; jakmile se má něco dělat, přijde ke slovu implementace, a tu rozhraní nemá ►Rozhraní je jako politik či ideolog: vyhlásí, jak má něco vypadat a jak se to má chovat, ale odpracovat to musí někdo jiný ►Třída se může přihlásit k tomu, že implementuje dané rozhraní ● Přihlašuje se k tomu veřejně ve své hlavičce; tím se toto prohlášení stává součástí její signatury a překladač bude kontrolovat jeho naplnění ● Instance třídy, která implementuje nějaké rozhraní, se mohou vydávat za instance daného rozhraní ● Třída může implementovat několik rozhraní současně, její instance se pak mohou vydávat za instance kteréhokoliv z nich ►Kdykoliv se hovoří o instanci rozhraní, hovoří se ve skutečnosti o instanci nějaké třídy, která dané rozhraní implementuje

24 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 24 ►Hlavička třídy: public class Semafor implements ISemafor ►Má-li být třídě povoleno vytváření instancí, musí implementovat všechny metody, které jí implementovaná rozhraní deklarují ►Pokud tak třída neučiní, musí se sama prohlásit za abstraktní a nemůže mít vlastní instance ►Třídu, která může vytvářet své instance, (tj. má implementované všechny metody, které slíbila implementovat), označujeme jako konkrétní Implementace rozhraní třídou1/2

25 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 25 Implementace rozhraní třídou2/2 Deklarovaná metoda, kterou musí všechny implementující třídy implementovat

26 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 26 Rozhraní v BlueJ (Demo) ►Rozhraní vytváříme stejně jako třídu, pouze v dialogovém okně nastavíme přepínač Typ třídy na hodnotu Rozhraní ►Implementaci rozhraní zadáme ● Ručně přímým zápisem v kódu ● Natažením šipky od třídy k implementovanému rozhraní ►Implementaci rozhraní zrušíme ● Ručně přímým smazáním v kódu ● Klepnutím na šipku (tím ji vybereme) a zadáním příkazu Odstranit z její místní nabídky ►Demo: A06_1_Rozhraní.htm

27 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 27 Trocha terminologie ►API – Application Programming Interface ● Aplikační programátorské rozhraní – rozhraní určené pro programátory, jejichž programy s danou aplikací komunikují ● V Javě je vytváříme z dokumentačních komentářů programem javadoc ● Zahrnuje signaturu i kontrakt ►GUI – Graphical User Interface ● Grafické uživatelské rozhraní – definuje formu prezentace výsledků a způsob komunikace uživatele s programem ● GUI nemá žádnou přímou vazbu na API ►Rozhraní × interface ● Pod termínem rozhraní budu rozumět souhrn informací, které o entitě její okolí ví, tj. signaturu + kontrakt ● Termín interface budu používat, když budu hovořit o programové konstrukci ● Nebude-li hrozit nedorozumění, budu i pro interface používat termín rozhraní

28 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 28 Proč používat interface ►Odděluje třídy, které by na sobě jinak vzájemně závisely, a umožňuje je pak měnit nezávisle na sobě (viz NV Most) ►Umožňuje deklarovat požadované vlastnosti zpracovávaných objektů bez ohledu na to, čí instancí tyto objekty budou (viz NV Služebník) ►Umožňuje definovat obecněji koncipované služby (metody) ►Umožňuje zobecnit společné vlastnosti skupiny tříd a definovat pak metody schopné pracovat s instancí kterémkoliv třídy z dané skupiny

29 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 29 Příklad – rozhraní ITvar v projektu Tvary

30 Vaše jistota na trhu IT Návrhový vzor Služebník ►Motivace ►Implementace ►Diagramy tříd obou možných užití ►Příklad: Plynule posuvné tvary ►Příklad: Blikající světlo 286–290

31 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 31 Služebník – motivace ►Několik tříd potřebuje definovat stejnou činnost a nechceme definovat na několika místech stejný kód ►Objekt má úkol, který naprogramovat buď neumíme, nebo bychom jej sice zvládli, ale víme, že je úloha již naprogramovaná jinde ►Řešení: Definujeme či získáme třídu, jejíž instance (služebníci) budou obsluhovat naše instance a řešit úkoly místo nich ● Řešení pak bude na jednom místě a bude se snáze spravovat ►Postup se hodí i když připravujeme řešení, které chceme definovat dostatečně obecné, aby je mohli používat všichni, kteří je budou v budoucnu potřebovat, a přitom nevíme, kdo budou ti potřební

32 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 32 Služebník – implementace ►Služebník nepracuje sám, ale komunikuje s obsluhovanými instancemi ►Aby mohl instance bezproblémově obsluhovat, klade na ně požadavky, co všechno musejí umět ►Služebník proto: ● Definuje rozhraní, v němž deklaruje své požadavky ● Jeho obslužné metody budou jako své parametry akceptovat pouze instance deklarovaného rozhraní ►Instance, která chce být obsloužena: ● Musí implementovat dané rozhraní, aby se mohla vydávat za jeho instanci ● Implementací rozhraní deklaruje, že umí to, co od ní služebník k její plnohodnotné obsluze požaduje

33 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 33 Klient posílá zprávu obsluhované instanci a ta předá požadavek služebníku, který jej realizuje; klient nemusí o služebníku vědět Služebník – diagramy tříd Klient posílá zprávu přímo služebníku a v parametru mu současně předává instanci, kterou má obsloužit

34 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 34 Příklad 1: Plynule posuvné objekty ►Objekty projektu Tvary se umí přesouvat pouze skokemTvary ►Pokud bychom chtěli, aby se přesouvaly plynule, museli bychom do každého z nich přidat příslušné metody, které by však byly u všech tříd téměř totožné ►Seženeme si služebníka – instanci třídy Přesouvač ►Tito služebníci vyžadují od obsluhovaných objektů implementaci rozhraní IPosuvný deklarujícího metody: ● Pozice getPozice(); ● void setPozice( Pozice pozice ); ● void setPozice( int x, int y ); ►Zato nabízí možnost volat metody: ● void přesunO ( IPosuvný ip, int dx, int dy ); ● void přesunNa( IPosuvný ip, int x, int y ); ● void přesunNa( IPosuvný ip, Pozice pozice );

35 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 35 Příklad 2: Blikající světlo ►Chceme po instancích třídy Světlo, aby uměly blikat zadanou dobu nezávisle na jiné činnosti ►Cyklus je nepoužitelný, protože po dobu jeho provádění ostatní činnosti stojí ● Takto není možno naprogramovat ukazatel směru jedoucího auta ►Využijeme služeb instancí třídy Opakovač, jejichž metody umějí opakovat klíčové činnosti svých parametrů ►Opakovač od obsluhovaných vyžaduje, aby implementovali rozhraní IAkční s metodou akce(), kterou bude opakovač zadaný-počet-krát opakovat ►Demo: D03-2: Blikání světlaD03-2: Blikání světla

36 Vaše jistota na trhu IT Návrhový vzor Prostředník ►Motivace ►Implementace ►Příklad: Plátno × Správce plátna 286–290 Mediator

37 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 37 Motivace ►Objekty se při pohybu nejprve smažou v původní pozici, aby se pak nakreslily v nové; při tom občas odmažou i část svých kolegů ►Aby objekt mohl zrekonstruovat svůj obraz, musel by mu někdo poslat zprávu ►Vysílač je vždy závislý na příjemci, protože změna jeho rozhraní může ovlivnit požadovaný způsob zasílání zpráv ►Když bude každý umět každému poslat zprávu, velmi se zvýší počet vzájemných závislostí, které zhoršují spravovatelnost ● Každá změna nás nutí zkontrolovat všechny závislé objekty ● Musí-li se změnit závislý objekt, dominovým efektem se problém propaguje na všechny objekty, které jsou na něm závislé

38 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 38 Prostředník – implementace ►Obdobný problém byl i u telefonů – obdobné je i řešení ● Telefony také nejsou spojeny každý s každým, ale spojují se prostřednictvím ústředny ►Definujeme objekt prostředníka, který zprostředkovává veškerou komunikaci objektů ● Vzájemné závislosti objektů se tak omezí na závislost na prostředníku ►V našem projektu nahradíme plátno správcem plátna ● Má na starosti správný vzhled ● Když objekt mění svoji podobu, řekne správci ● Správce pak požádá o překreslení všechny, jichž se to týká ►Prostředník je většinou implementován aplikací návrhového vzoru Pozorovatel – viz dále

39 Vaše jistota na trhu IT Návrhový vzor Pozorovatel/Posluchač ►Motivace ►Implementace ►Diagramy tříd obou možných užití ►Příklad: Blikající světlo ►Příklad: Plynule posuvné tvary Observer / Listener

40 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 40 Posluchač – motivace Objekt čekající na výskyt nějaké události – má dvě možnosti: ►Neustále se ptát iniciátora události, zda už nastala ● Oslík v 2. dílu Shreka se neustále ptá „Už tam budem?“ ● Řidič čekající na zelenou neustále sleduje semafor ►Dohodne se s iniciátorem, že dohodnutým způsobem oznámí, až událost nastane ● V lůžkovém vlaku vás průvodčí vzbudí před cílovou stanicí ● Řidič na semaforu v klidu čte mapu v očekávání, že ti za ním na něj zatroubí ● SMS oznámí příchod peněz na konto ►Návrhový vzor pozorovatel řeší problém druhým způsobem, je však třeba dohodnout způsob oznámení výskytu události ►Vzor je někdy označován jako vzor vydavatel—předplatitel (publisher—subscriber)

41 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 41 Posluchač – implementace ►Posluchač (pozorovatel, předplatitel) se musí přihlásit u vysílače (pozorovaného, vydavatele) ►Vysílač je ochoten přijmout přihlášku pouze od objektů implementujících rozhraní definující jak objektu oznámit, že došlo k očekávané události ►Posluchač se po přihlášení o událost dál nestará a hledí si svého ►Až vysílač zavolá dohodnutou metodu, pak zareaguje ►Událostmi řízené programování

42 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 42 Příklad: Správce plátna ►Kdo chce být zobrazován na plátně, musí se přihlásit u instance třídy SprávcePlátna ►Správce registruje pouze instance rozhraní IKreslený, tj. instance tříd, jež je implementují ►Kdykoliv se dozví, že se situace na plátně změnila, nechá jednoho po druhém překreslit ►Objekt předem neví, kdy bude pořádán, aby se překreslil ►Aby se objekty nemohly kreslit, kdy si vzpomenou, je plátno majetkem správce a je na ně možno kreslit pouze kreslítkem, které obdrží překreslovací metoda jako parametr

43 Vaše jistota na trhu IT Návrhový vzor Most ►Motivace ►Klasicky navržená kalkulačka ►Kalkulačka po aplikaci vzoru Most ►Zisk z aplikace vzoru ►Testování sady programů

44 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 44 Most – motivace ►Klient komunikuje se třídou, která je pouze zprostředkovatelem (abstrakcí) nabízené služby; vlastní realizaci má na starosti jiná třída (implementace) ►Vložíme-li mezi abstrakci a implementaci rozhraní, oddělíme je a můžeme měnit jednu nezávisle na druhé ►S aplikací tohoto vzoru se setkáte (alespoň někteří) ve vaší první semestrální práci

45 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 45 Klasicky navržená kalkulačka ►Klasický přístup (viz skripta) ● Odděluje se návrh CPU and GUI; – Třídu GUI navrhuje vyučující – Třídu CPU navrhují studenti ● Stisk tlačítka z každé skupiny volá partnerskou metodu v CPU ►Třídy jsou těsně provázané což má své nepříjemné důsledky: ● S každou změnou definice CPU je třeba změnit definic GUI a naopak ● Každá verze studentského zadání vyžaduje vlastní verzi definice GUI ● Chceme-li po studentech, aby u zkoušky svoji třídu upravili, musíme příslušně upravit i námi definované GUI ►Uvedený přístup je nutný v případě neznají-li studenti rozhraní

46 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 46 Po aplikaci vzoru Most ►Třída CPU implementuje rozhraní ICPU deklarující tři metody: ● RozměrKláves getRozměr() ● List getPopisky() ● String stisknuto( String label ) ►Konstruktor třídy GUI ● Dostane instanci of CPU jako parametr ● Zeptá se jí na požadovaný rozměr klávesnice a seznam požadovaných popisků na tlačítcích ● Připraví GUI podle obdržených požadavků ►Běh programu: ● Instance GUI zjistí, jaké tlačítko bylo stisknuto a zašle instanci CPU zprávu s jeho popiskem ● Instance CPU zjistí, co stisk znamená, a vrátí GUI nový obsah displeje

47 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 47 Co jsme tím získali ►GUI může spolupracovat s různými CPU; stačí, aby spolupracující CPU implementovala rozhraní ICPU ►Přiblížíme studentům význam a použití rozhraní ►Ukážeme, že tvůrce GUI nemusí znát spolupracující CPU předem, instance GUI se ji může dozvědět až při svém zrodu ►Můžeme do CPU svobodně přidávat další a další funkce, aniž bychom museli jakkoliv upravovat třídu GUI ►Můžeme připravit automatické testy

48 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 48 ►Testovací třída se bude tvářit, že je zvláštní GUI ►Třída Verze dodá požadovanou sadu popisků spolu s testy definujícími požadované reakce na stisk kláves ►Rozhraní ICPU rozšíříme o metodu vracející pořadí řešeného zadání int getZadání() ►Můžeme přidat značkovací rozhraní IGUI, jež budou implementovat třídy, které se chtějí vydávat za GUI Testování sady programů

49 Vaše jistota na trhu IT Dědičnost a dědění ►Princip ►3 typy dědění ►Implementace rozhraní jak realizace dědičnosti typů ►Dědění rozhraní ►Rozhraní s několika bezprostředními předky ►Princip dědičnosti implementace

50 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 50 Princip ►Mezi instancemi nějakého typu se často najde skupina instancí se společnými speciálními vlastnostmi ● Notebooky či sálové počítače jsou speciální druhy počítačů ● Psy, kočky, koně atd. jsou speciální druhy savců ● HTML dokumenty jsou speciálním druhem dokumentů ►OOP umožňuje definovat podtyp charakterizující tuto skupinu; pro značení obou typů používáme názvy: ● Podtyp– Nadtyp ● Předek– Potomek ● Základní– Odvozený typ ● Rodičovský– Dceřiný ►Instance potomka přebírají rozhraní svého rodiče – říkáme, že je zdědí ● Instance potomka jsou pouze speciální podmnožinou instancí rodiče, proto se mohou kdykoliv vydávat (alespoň formálně) za instance rodiče

51 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 51 3 typy dědění1/2 ►Dědění typů ● Potomek dodrží všechny vlastnosti a schopnosti předka, tj. převezme jeho signaturu a dodrží jeho kontrakt, a může se proto kdykoliv plnohodnotně vydávat za předka ● Příklad: třída implementující nějaké rozhraní ►Dědění implementace ● Potomek převezme od předka jeho implementaci, takže převzaté funkce nemusí definovat sám ● Příklad: Všechny třídy přebírají základní metody od třídy Object ● Nebezpečí: při přizpůsobování zděděných entit potřebám potomka není občas dodržen kontrakt předka ►Přirozené dědění ● Jak chápeme vztah obecný-speciální bez ohledu na programování ● Příklad: Čtverec je speciální druh obdélníku, ale nemůže se vydávat za obecný obdélník, protože namůže libovolně změnit velikost svých stran

52 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 52 3 typy dědění2/2 ►V dobře napsaném programu jsou všechny tři typy dědění v harmonii ● Je-li jeden aspekt použité dědičnosti v rozporu s ostatními, narušuje se stabilita programu a jeho rozšiřitelnost ►Při implementaci rozhraní a při jejich dědění se uplatní pouze dědění typů, protože interface žádnou implementaci nemá ►Dědění implementace svádí programátory k použití, které je v rozporu s děděním typů, a proto je vykládáme až po zvládnutí dědění typů

53 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 53 Implementace rozhraní ►Při implementaci rozhraní se implementující třída zavazuje implementovat všechny jím deklarované metody a dodržet jejich kontrakt ►Třída pak může vydávat svoje instance za instance daného rozhraní, tj. instance potomka se může vydávat za instanci předka ►Podmínkou správné funkce je dodržení kontraktu; ten ale překladač zkontrolovat nedokáže, takže je plně na bedrech programátora Opakování

54 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 54 Dědění rozhraní ►Při dědění rozhraní potomek deklaruje, kdo je jeho předek ►V Javě smí interface deklarovat více předků současně public interface Potomek extends Předek1, Předek2 ►Potomek přebírá všechny deklarace všech předků a může přidat i svoje vlastní ►Třída implementující potomka implementuje každého z jeho předků ►=> třída implementující rozhraní může svoji instanci vydávat nejenom za instanci daného rozhraní, ale také za instanci kteréhokoliv z jeho předků

55 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 55 Použití dědění několika rozhraní ►Metoda vyžaduje, aby její parametr implementoval dvě různá rozhraní ►Java neumožňuje deklarovat, že parametr je současné instancí dvou různých typů ►Tuto nemožnost lze obejít tak, že definujeme interface, který je potomkem obou rozhraní, a deklarujeme parametr jako instanci tohoto potomka

56 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 56 Ukázka použití dědičnosti rozhraní

57 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 57 Ukázky definic public interface IKreslený { public void nakresli( Kreslítko kreslítko ); } public interface IPosuvný extends IKreslený { public Pozice getPozice(); public void setPozice( Pozice pozice ); public void setPozice( int x, int y ); } public interface INafukovací extends IKreslený { public Rozměr getRozměr(); public void setRozměr( Rozměr rozměr ); public void setRozměr( int šířka, int výška ); } public interface IHýbací extends IPosuvný, INafukovací {}

58 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 58 Rozhraní s více přímými předky ►Má-li rozhraní několik rodičů, může se stát, že více z nich deklaruje metody se shodnou signaturou ►Zdědí-li potomek z několika stran metody se shodnou signaturou, musí mít všechny stejný kontrakt, protože Java je všechny považuje za deklaraci stejné metody

59 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 59 Princip dědičnosti implementace ►Dědičnost implementace je speciální případ skládání, při němž se „spolknutým“ objektem převezmu i jeho rozhraní ►Objekt, který je přebírán i s jeho rozhraním označujeme jako rodičovský podobjekt ►Metody a atributy rodičovského podobjektu označujeme jako zděděné ►Při obdržení zprávy (volání metody) z rodičovského rozhraní instance reaguje jedním ze dvou způsobů podle toho, zda má definovanou vlastní verzi příslušné metody: ● Má-li ji definovánu, zavolá ji ● Nemá-li ji definovánu, zavolá rodičovskou verzi ►Neexistuje způsob, jak zvenku zavolat rodičovskou verzi metody, která je překrytá verzí definovanou v dceřiné třídě

60 Vaše jistota na trhu IT Návrhový vzor Dekorátor

61 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 61 Motivace ►V knihovně potřebujeme nabízet třídy‘ poskytující různé kombinace funkcionalit ►Při nutnosti nabízet téměř všechny možné kombinace roste počet potřebných tříd kombinatoricky = neúnosně ►S každou další přidanou funkcionalitou musíme přidat násobek dosud existujících tříd ►S každou přidanou základní třídou musíme přidat i třídy pro možné kombinace přidaných funkcionalit

62 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 62 Charakteristika ►Návrhový vzor Dekorátor umožňuje snížit kombinatoricky rostoucí počet tříd ►Každá dodaná funkčnost je implementována jako „ozdobení“ (dekorování) jiného objektu ►Dekorátor rozšiřuje (zdobí) objekt, ne třídu; na rozdíl od statické dědičnosti pracuje dynamicky ►Základní třídy i dekorátory mají společného rodiče ►Příklad ● Knihovna proudů java.io (s bufferem, řádkováním, daty, …) ● swing (pole, s posuvníkem, s okrajem, s oběma, …)

63 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 63 Implementace1/2 ►Zabalit objekt do objektu poskytujícího novou funkcionalitu, který tak původní objekt ozdobí (dekoruje) novou funkcionalitou ►Pro každou novou funkcionalitu pak bude stačit přidat pouze jedinou obalovou (dekorující) třídu ►Konstruktor dekorátoru přebírá dekorovaný objekt jako parametr a „obalí“ jej vlastními schopnostmi ►Dekorátor většinou přidává metody, které se starají o jím přidanou funkčnost. Může ale také pouze překrýt metody svých předků a definovat je pro daný účel efektivněji ►Požadavky nesouvisející s dodatečnou funkčností předá dekorátor dekorovanému objektu a vrátí obdržený výsledek

64 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 64 Implementace2/2 ►Přidávané funkcionality je možné kumulovat, tj. zabalený objekt lze znovu zabalit do objektu přidávajícího další funkcionalitu ● Výsledný objekt lze vytvářet postupně: IAuto benzin = new Benzin(); IAuto abs = new ABS( benzin ); AAuto auto = new Automat(abs); ● Nebo najednou AAuto auto1 = new Automat( new ABS(new Benzin()) ); AAuto auto2 = new Automat( new ABS( new Benzin()) ); ►Dekorátory mají někdy ještě vlastního rodiče se společnou implementací. ►Ten pak bývá koncipován jako adaptér nabízející implicitní funkčnost: delegování metod na obalený objekt a vracení obdržených výsledků

65 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 65 Struktura tříd při implementaci vzoru Dekorátor ►Dekorátor pracuje jako obálka kolem dekorovaného objektu zabezpečující dodatečnou funkčnost ►Občas bývá nazýván Wrapper

66 Příklad – diagram tříd bez dekorátoru VŠE – 03 Copyright © 2006, Rudolf Pecinovský 66

67 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 67 Příklad – diagram tříd s dekorátorem

68 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 68 Příklad – ukázka implementace public class Okružní implements IMultiposuvný { //... Vynechané deklarace public Okružní(IPosuvný dekorovaný) { this.dekorovaný = dekorovaný; public Pozice getPozice() { return dekorovaný.getPozice(); public void setPozice(Pozice pozice) { dekorovaný.setPozice(pozice); public void přesunuto() { // Tělo metody přidávající funkčnost } //...Další definované metody }

69 Vaše jistota na trhu IT Třída Object a její metody

70 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 70 Třída Object ►Všechny objekty obsahují odkaz na rodičovský podobjekt, jenž je instancí třídy Object ►Všechny třídy přebírají rozhraní třídy Object, a mohou proto vydávat svoje instance za instance třídy Object ►Známe-li vlastní třídu dané instance, můžeme instanci vydávající se za instanci třídy Object přetypovat na instanci její mateřské třídy public class Pozice { public final int x, y; //... Vynechané metody public boolean equals( Object o ) { if( !(o instanceof Pozice) ) return false; Pozice p = (Pozice) o; return (x == p.x) && (y == p.y); }

71 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 71 Rozhraní třídy Object ► public boolean equals(Object obj) ► public int hashCode() ► public final Class getClass() ► public String toString() ► protected void finalize() throws Throwable ► protected Object clone() throws CloneNotSupportedException ► public final void notify() public final void notifyAll() public final void wait() public final void wait(long timeout) public final void wait(long timeout, int nanos) throws InterruptedException

72 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 72 Metody třídy Object v BlueJ ►V BlueJ uvádějí objekty metody zděděné od třídy Object ve zvláštní nabídce ►Definuje-li metoda vlastní verzi, je v této nabídce uvedeno, že metoda je překrytá … ►a příslušný příkaz je zopakován v nabídce daného objektu ►Při zavolání překryté metody se zavolá dceřiná, překrývající metoda

73 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 73 Metoda equals(Object) ► public boolean equals(Object obj) ►Metoda musí umět porovnat objekt s jakýmkoliv jiným objektem ►Měla by být (pro běžné situace musí být): ● Reflexivní: a.equals(a) == true ● Symetrická: a.equals(b) == b.equals(a) ● Tranzitivní: a.equals(b) & b.equals(c) <= a.equals(c) ● Stabilní: co platí teď, musí platit pořád (proto musí být hodnotové objekty neměnné) ● Synchronizovaná s metodou hashCode() public class Pozice { public final int x, y; //... Vynechané metody public boolean equals( Object o ) { if( !(o instanceof Pozice) ) return false; Pozice p = (Pozice) o; return (x == p.x) && (y == p.y); }

74 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 74 Metoda hashCode() ► public int hashCode() ►Přiřazuje instanci celé číslo používané při ukládání instance do hešových tabulek ►Musí platit ● a.equals(b) => a.hashCode() == b.hashCode() ►Mělo by platit ● Hodnoty musí být co nejrovnoměrněji rozprostřeny ● Hodnota musí být spočtena dostatečně rychle

75 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 75 Metoda getClass() ► public final Class getClass() ►Metoda je konečná => není ji možné překrýt ►Metoda vrací class-objekt třídy dané instance; class-objekt třídy je instance třídy Class ● Class-objekt třídy Class je také instancí třídy Class ►Zjištění úplného názvu třídy instance iii : String s = iii.getClass().getName(); ►Zjištění vlastního názvu třídy (tj. bez balíčků) instance iii : String s = iii.getClass().getSimpleName(); ►Class-objekt třídy lze získat i jako literál: Třída.class ►Některé metody vyžadují class-objekt jako parametr

76 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 76 Metoda toString() ► public String toString() ►Vrací řetězcovou reprezentaci dané instance, tj. podobu instance převedené na textový řetězec ►Implicitní verze definovaná třídou Object vrací getClass().getName() + + Integer.toHexString(hashCode()) ►Metodu volá operátor sčítání při „sčítání“ instance s řetězcem a z toho plynoucímu převodu instance na textový řetězce, ► "" + objekt dá stejný výsledek jako objekt.toString() ►Metodu toString() by měla definovat každá třída

77 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 77 Metoda finalize() ► protected void finalize() throws Throwable ►Metodu volá uklizeč při odstraňování instance z haldy; metoda má za úkol „uklidit“ prostředky alokované instancí ►Nikdy není zaručeno, kdy se uklizeč (garbage collector) rozhodne instanci odstranit a dokonce ani to, zda ji do ukončení aplikace vůbec odstraní (může předat operačními systému nevyčištěnou paměť) ►Je to metoda posledního zoufalství, když neumíme úklid (např. zavření otevřených souborů) zařídit lépe ►Metodu lze využít pro kontrolu toho, zda program po instanci opravdu uklidil – objeví-li metoda neuklizené zbytky, znamená to chybu v programu

78 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 78 Metoda clone() ► protected Object clone() throws CloneNotSupportedException ►Vytváří kopii daného objektu, pro níž by mělo platit: ● x.clone() != x ● x.clone().getClass() == x.getClass() ● x.clone().equals(x) ►Předchozí pravidla není nutné dodržet, ale k jejich nedodržení je třeba mít pádný důvod ►Implicitní implementace je dodržuje, navíc vyžaduje, aby třída implementovala rozhraní Cloneable v opačném případě vyhodí CloneNotSupportedException

79 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 79 Rozhraní Cloneable ►Rozhraní Cloneable je „značkovací“ rozhraní, tj. rozhraní, které nevyžaduje implementaci žádné metody ►Implementací rozhraní se třída pouze zavazuje splnit kontrakt, jenž pouze vyžaduje, aby byla korektně implementována metoda clone(), a současně ostatním povoluje vytvářet kopie jejích instancí klonováním ►Překryvná verze metody clone() může pro vytvoření kopie volat konstruktor nebo využít rodičovské verze super.clone() (využití druhé možnosti je výrazně častější) ►Metoda clone() je chráněná ( protected ) ; chceme-li ji zveřejnit, stačí v řadě případů jednoduchá definice public Object clone() { return super.clone(); }

80 VŠE – 03 Copyright © 2006, Rudolf Pecinovský 80 Metody pro synchronizaci vláken ► public final void notify() Oznamuje monitoru, že stav sdíleného prostředku se změnil ► public final void notifyAll() Jako předchozí, ale vzbudí se všechna čekající vlákna ► public final void wait() public final void wait(long timeout) public final void wait(long timeout, int nanos) throws InterruptedException Oznamuje monitoru, že čeká na změnu stavu daného prostředku; dobu čekání může omezit parametrem ►Všechny synchronizační metody jsou konečné a není je tedy možné překrýt

81 Vaše jistota na trhu IT Děkuji za pozornost ►Rudolf Pecinovský mail: ICQ:


Stáhnout ppt "Vaše jistota na trhu IT Rozhraní Rudolf Pecinovský"

Podobné prezentace


Reklamy Google