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ý rudolf@pecinovsky.cz

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: ● @author –autor třídy (podepisujte své programy) ● @version –verze programu (uvádějte, budete-li program vylepšovat) ►Dokumentace metody: ● @param –význam parametru (název za značku musí být odpovídat názvu parametru v hlavičce metody) ● @return –popis toho, co metoda vrací ►Značky v textu komentáře: ● {@code ?} –text ? bude vysazen neproporcionálním písmem ● {@link ?} –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 {@code Světlo} představují simulace * rozsvítitelných a zhasnutelných pohyblivých světel. * * @author Rudolf Pecinovský * @version 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. * * @param x Vodorovná souřadnice vytvářeného světla * @param 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. * * @param x Vodorovná souřadnice vytvářeného světla * @param y Svislá souřadnice vytvářeného světla * @param 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 {@code Šablona} představují... * * @author jméno autora * @version 0.00.000, 0.0.2006 */ 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. * * @author Rudolf Pecinovský * @version 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. * * @param x Vodorovná souřadnice vytvářeného světla * @param 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. * * @param x Vodorovná souřadnice vytvářeného světla * @param y Svislá souřadnice vytvářeného světla * @param průměr Průměr kruhu simulujícího světlo * @param 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 http://java.sun.com/docs/codeconv/ http://java.sun.com/docs/codeconv/ ►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ů. * @param pozor Doba, po níž bude svítit samotná oranžová * @param stop Doba, po níž bude svítit samotná červená * @param připravit Doba, po níž bude svítit červená s oranžovou * @param 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ý; } @Override public Pozice getPozice() { return dekorovaný.getPozice(); } @Override public void setPozice(Pozice pozice) { dekorovaný.setPozice(pozice); } @Override 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: rudolf@pecinovsky.cz ICQ: 158 156 600


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

Podobné prezentace


Reklamy Google