Olio-ohjelmointi Suunnittelumallit Proxy, Factory Method, Prototype ja Singleton. 1. Proxy (Edustaja)

Samankaltaiset tiedostot
812347A Olio-ohjelmointi, 2015 syksy 2. vsk. IX Suunnittelumallit Proxy, Factory Method, Prototype ja Singleton

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. VII Suunnittelumallit Adapter ja Composite

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. VIII Suunnittelumallit Observer ja State

Ohjelmistotekniikan menetelmät, suunnittelumalleja

Olio-ohjelmointi Johdanto suunnittelumalleihin. 1. Yleistä

Kooste. Esim. Ympyrän keskipiste voidaan ajatella ympyrän osaksi.

812341A Olio-ohjelmointi Peruskäsitteet jatkoa

Olio-ohjelmointi Suunnittelumallit Adapter ja Composite. 1. Adapter

T SEPA - päiväkirja: Design Patterns. ETL työkalu

4. Luokan testaus ja käyttö olion kautta 4.1

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Rajapinnat ja sisäluokat

812341A Olio-ohjelmointi, IX Olioiden välisistä yhteyksistä

Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä

Rajapinnasta ei voida muodostaa olioita. Voidaan käyttää tunnuksen tyyppinä. Rajapinta on kuitenkin abstraktia luokkaa selvästi abstraktimpi tyyppi.

Kertaus: yleistys-erikoistus ja perintä

Ohjelmistojen mallintaminen viikon 4 laskareiden mallivastauksia

T Henkilökohtainen harjoitus: FASTAXON

Sisällys. 11. Rajapinnat. Johdanto. Johdanto

Tenttikysymykset. + UML-kaavioiden mallintamistehtävät

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Sisältö. 2. Taulukot. Yleistä. Yleistä

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma.

Oliosuunnittelu. Oliosuunnittelu

Ohjelmoinnin peruskurssien laaja oppimäärä

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa();

Olio-ohjelmointi Javalla

Ohjelmistojen mallintaminen, suunnittelumalleja

Sisällys. 7. Oliot ja viitteet. Olion luominen. Olio Java-kielessä

UML ja luokkien väliset suhteet

A) on käytännöllinen ohjelmointitekniikka. = laajennetaan aikaisemmin tehtyjä luokkia (uudelleenkäytettävyys)

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. VI Johdanto suunnittelumalleihin

T SEPA - päiväkirja: Design Patterns. ETL työkalu

Sisällys. JAVA-OHJELMOINTI Osa 7: Abstrakti luokka ja rajapinta. Abstraktin luokan idea. Abstrakti luokka ja metodi. Esimerkki

Sisältö. 22. Taulukot. Yleistä. Yleistä

4. Olio-ohjelmoinista lyhyesti 4.1

2. Olio-ohjelmoinista lyhyesti 2.1

Sisällys. 9. Periytyminen Javassa. Periytymismekanismi Java-kielessä. Periytymismekanismi Java-kielessä

Javan perusteita. Janne Käki

Muusta kuin vesisioista

Ohjelmistojen suunnittelu

7. Oliot ja viitteet 7.1

HELIA 1 (14) Outi Virkki Käyttöliittymät ja ohjlmiston suunnittelu

9. Periytyminen Javassa 9.1

Suunnittelumallien käyttö ohjelmistosuunnittelussa

Sisällys. 18. Abstraktit tietotyypit. Johdanto. Johdanto

Hirviö. Design Patterns

15. Ohjelmoinnin tekniikkaa 15.1

TIE Ohjelmistojen suunnittelu

Ohjelmoinnin jatkokurssi, kurssikoe

Sisällys. JAVA-OHJELMOINTI Osa 6: Periytyminen ja näkyvyys. Luokkahierarkia. Periytyminen (inheritance)

Olio-ohjelmointi Suunnittelumallit Observer ja State. 1. Observer (Tarkkailija)

Hakemistojen sisällöt säilötään linkitetyille listalle.

KERROSARKKITEHTUURIN SUUNNITTELUMALLIT. Kuisma Lehtonen Joensuun yliopisto Tietojenkäsittelytiede Pro gradu -tutkielma

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op

Muutamia peruskäsitteitä

12. Monimuotoisuus 12.1

Tarjolla tänää: Ohjelmiston toteutuksesta. Kuinka tulla hyväksi ohjelmoijaksi? CRC-kortit. Testilähtöinen kehittäminen JOT2007. Uudelleenrakentaminen

Olio-ohjelmointi: Luokkien toteuttaminen. Jukka Juslin

Sokkelon sisältö säilötään linkitetyille listalle ja tekstitiedostoon. Työ tehdään itsenäisesti yhden hengen ryhmissä. Ideoita voi vaihtaa koodia ei.

Rajapinnat ja olioiden välittäminen

2. Olio-ohjelmoinnin perusteita 2.1

18. Abstraktit tietotyypit 18.1

Web-palvelu voidaan ajatella jaettavaksi kahteen erilliseen kokonaisuuteen: itse palvelun toiminnallisuuden toteuttava osa ja osa, joka mahdollistaa k

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

Tenttikysymykset. + UML- kaavioiden mallintamistehtävät

9. Periytyminen Javassa 9.1

Tämän lisäksi listataan ranskalaisin viivoin järjestelmän tarjoama toiminnallisuus:

T Ohjelmistojen määrittely- ja suunnittelumenetelmät Harjoitustyöraportti TNT - Tarkistetaan Ne Tentit Arkkitehtuuri- ja suunnittelumalli

Uudelleenkäytön jako kahteen

Sisällys. Metodien kuormittaminen. Luokkametodit ja -attribuutit. Rakentajat. Metodien ja muun luokan sisällön järjestäminen. 6.2

Ohjelmoinnin peruskurssien laaja oppimäärä

Aalto Yliopisto T Informaatioverkostot: Studio 1. Oliot ja luokat Javaohjelmoinnissa

Plugin-pohjaiset sovellukset arkkitehtuurit

SEPA - Design Patterns

Rajapinta (interface)

UML Luokkakaavio 14:41

Joskus yleistäminen voi tapahtua monen ominaisuuden pohjalta. Myös tällöin voi tulla moniperintätilanteita.

UML -mallinnus LUOKKAKAAVIO EERO NOUSIAINEN

POLKU LUOKKAKAAVIOISTA TAULUJEN TOTEUTUKSEEN

Ohjelmistojen mallintamisen ja tietokantojen perusteiden yhteys

12. Kehysarkkitehtuurit

11/20: Konepelti auki

TIE Samuel Lahtinen. Lyhyt UML-opas. UML -pikaesittely

S11-09 Control System for an. Autonomous Household Robot Platform

Sisällys. Mitä on periytyminen? Yksittäis- ja moniperiytyminen. Oliot ja perityt luokat. Periytymisen käyttö. 8.2

Osoitin ja viittaus C++:ssa

15. Ohjelmoinnin tekniikkaa 15.1

Kehitysohje. ETL-työkalu. ExtraTerrestriaLs / Aureolis Oy

Mitä on periytyminen?

Sisällys. 6. Metodit. Oliot viestivät metodeja kutsuen. Oliot viestivät metodeja kutsuen

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

Sisällys. 19. Unified Modeling Language (UML) Johdanto. Johdanto. Johdanto. Luokkakaavio:

Harjoitustehtävät ja ratkaisut viikolle 48

12. Monimuotoisuus 12.1

Interaktiivisten järjestelmien arkkitehtuuriratkaisu, jolla käyttöliittymä erotetaan sovelluslogiikasta.

Ylläpitodokumentti. Boa Open Access. Helsinki Ohjelmistotuotantoprojekti HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos

16. Javan omat luokat 16.1

Hirviö. Design Patterns

Digi-tv vastaanottimella toteutetut interaktiiviset sovellukset

on ohjelmoijan itse tekemä tietotyyppi, joka kuvaa käsitettä

Transkriptio:

Olio-ohjelmointi Suunnittelumallit Proxy, Factory Method, Prototype ja Singleton Tässä osassa tutustutaan yhteen rakennemalliin (Proxy) ja kolmeen luontimalliin (Factory Method, ) teoksen [Gam] pohjalta. Luontimallit kuvaavat epäsuoria tapoja luoda olioita ohjelmassa. Niiden avulla järjestelmä voidaan tehdä riippumattomaksi siitä, miten sen oliot luodaan ja esitetään sekä miten niitä yhdistellään. Luokkamallit perustavat toimintansa perintään, kun oliomallit delegoivat olion luomisen toisille olioille. Luontimalleja tarvitaan erityisesti, kun ohjelmassa siirrytään käyttämään koosteolioita perimisen asemasta. Tällöin sopivien olioiden luominen voi vaatia mutkikkaampia toimenpiteitä kuin pelkkä alustaminen. 1. Proxy (Edustaja) Kun ohjelmassa luodaan erittäin massiivisia olioita, niitä ei kannattaisi pitää muistissa koko ohjelman suoritusaikaa vaan luoda ne tarvittaessa ja tuhota käytön jälkeen. Entä jos tällainen olio on osana toisessa oliossa? Isäntäolion rakenteen vuoksi suuri osaolio voidaan joutua luomaan ennenaikaisesti. Tällaisessa tapauksessa voidaan käyttää sijaisoliota, jonka rajapinta on sama kuin suuren olion ja joka huolehtii suuren olion luomisesta, kun sitä tosiasiassa tarvitaan. Tästä toimintatavasta syntyvää suunnittelumallia sanotaan Proxyksi eli Edustajaksi. Esimerkki. Dokumentissa voi esiintyä elementtinä suuri kuva. Sen sijaan, että kuva luettaisiin heti muistiin dokumenttia luotaessa, voidaan luoda kuvan tiedostonimellä tunnistettava Proxyolio, joka lisätään dokumenttiin. Proxy-olio luo kuvaolion vasta, kun dokumenttiolio näyttää kuvan. Proxy-mallia voidaan käyttää kaikissa tapauksissa, kun olioon on viitattava muuten kuin tavallisen suoran viitteen kautta. Etäedustajaa (remote proxy) käytetään viittamaan olioon, joka sijaitsee toisessa muistialueessa. Virtuaaliedustaja (virtual proxy) luo suuria olioita tarvittaessa, kuten aiemmassa esimerkissä Suojausedustaja (protection proxy) kontrolloi pääsyä olioon. Sitä voidaan käyttää erityisesti, kun on toteutettava erilaisia pääsyoikeuksia. Älykkäät osoittimet ovat myös proxyja. Älykäs osoitin on viite, johon on toteutettu muitakin toimintoja kuin pelkkä olioon viittaaminen. Se voi hoitaa esimerkiksi oliolle varatun muistin vapauttamisen, kun siihen ei enää ole viitteitä. 1

Mallin luokkarakenne on esitetty alla Kuva 1. Proxy-mallin luokkarakenne (Vrt. [Gam]) Mallista syntyvä oliorakenne voisi olla esimerkiksi Kuva 2. Proxy-mallin oliokaavio (Vrt. [Gam]) Mallin osallistujat ovat Proxy, joka säilyttää viitteen todelliseen kohdeolioon. Proxyn rajapinta on sama kuin kohdeolion, jotta sitä voidaan käyttää kohdeolion sijasta. Kontrolloi pääsyä todelliseen kohteeseen ja voi olla vastuussa sen luomisesta ja tuhoamisesta. Proxylla voi tyypistään riippuen olla myös muita vastuita. Kohde (Subject) määrittelee todellisen kohteen ja Proxyn yhteisen rajapinnan, jotta Proxya voidaan käyttää kaikkialla, missä todellista kohdetta oletetaan käytettävän. Todellinen kohde (RealSubject); kohde jonka sijaisena Proxy toimii. Proxy-mallin käyttämällä epäsuoralla olioon viittaamisella saavutetaan monia etuja, mm. voidaan piilottaa olion käyttäjiltä se, että olio sijaitsee toisessa osoiteavaruudessa. Edelleen voidaan tehdä optimointeja oliota käsiteltäessä, kuten luoda suuria olioita tarvittaessa. Varsinkin kielissä, joissa ei ole automaattista roskien keruuta, erilaiset Proxy-oliot voivat automatisoida muistin vapautuksen ja mahdolliset muut siivousoperaatiot olioita käytettäessä. 2

2. Factory Method (Tehdasmetodi) Moniin sovelluksiin liittyy jonkinlainen dokumenttiolio. Tällöin ohjelmassa esiintyy kaksi perusoliota: sovellusolio ja dokumenttiolio. Näiden perusluokat ovat yleensä abstraktit ja kukin sovellus vastaa konkreettisesta toteutuksesta. Näin ollen sovellusolio on vastuussa dokumentin luomisesta, mutta se ei tunne kuin dokumenttien abstraktin perusluokan eikä tiedä, minkälainen dokumentti on luotava. Tämä on luonnollisesti ongelmallista. Factory Method tarjoaa ratkaisun ongelmaan. Mallissa tehdään jokaista luotavaa dokumenttioliota vastaava sovellusluokan aliluokka. Tällöin sovellusluokan dokumentin luovan metodin kutsuminen ohjautuu dynaamisen sidonnan avulla oikealle aliluokalle, joka osaa luoda oikeantyyppisen dokumentin. Tämä tilanne voidaan luonnollisesti abstrahoida sovellusdokumenttiyhteydestä yleiseksi suunnittelumalliksi. Factory Method-suunnittelumallia käytetään, kun luokassa on luotava olioita, joiden tarkkaa tyyppiä ei tunneta ja halutaan antaa vastuu olioiden luomisesta aliluokille. Mallia voidaan käyttää myös, kun luokat jakavat vastuita useille avustavilla aliluokille ja halutaan säilyttää paikallisena tieto siitä, mitä apuluokkaa käytetään. Mallin luokkarakenne on esitetty seuraavassa kaaviossa: Kuva 3. Factory Method-mallin luokkakaavio (Vrt. [Gam]) Mallin osallistujat ovat Product, joka määrittelee FactoryMethodin luomien olioiden rajapinnan. ConcreteProduct toteuttaa Productin rajapinnan. Creator esittelee tehdasmetodin (FactoryMethod), joka palauttaa Product-tyyppisen olion. Voi myös määritellä oletustoteutuksen. Voi itse kutsua tehdasmetodia. ConcreteCreator uudelleenmäärittelee tehdasmetodin luodakseen Product-olion. Suunnittelumallia käyttämällä poistetaan tarve liittää ohjelmaan sovelluskohtaisia luokkia. Ohjelmassa käsitellään ainoastaan Product-rajapintaa, joten sovellus toimii minkä tahansa sen perivän konkreettisen luokan kanssa. Mallin käyttäminen voi kuitenkin johtaa monimutkaiseen luokkarakenteeseen, koska asiakasolioiden täytyy ehkä periä Creator-luokka luodakseen jonkin tietyn Product-luokan aliluokan olion. 3

Tehdasmetodia ei tarvitse välttämättä kutsua Creator-luokista. Kutsu voidaan tehdä myös ulkopuolisesta luokasta. Tällä menetelmällä voidaan kytkeä rinnakkaiset luokkarakenteet toisiinsa. Käsitellään lyhyesti vielä suunnittelumallin toteutusta. Voidaan käyttää kahta versiota: 1. Luokka Creator on abstrakti eikä tarjoa toteutusta tehdasmetodille 2. Luokka Creator on konkreettinen ja siinä on oletustoteutus tehdasmetodille. Ensimmäisessä tapauksessa Creator-luokan aliluokkien on pakko määritellä toteutus tehdasmetodille. Tätä menetelmää käytetään, kun Creator-luokan avulla luodaan olioita ennalta tuntemattomista luokista. Toinen tapaus on käytössä lähinnä mukavuussyistä: halutaan joustavuutta olioiden luomiseen. Tehdasmetodit voidaan myös parametrisoida. Tällöin luokan tehdasmetodi voi luoda useanlaisia olioita, kunhan ne toteuttavat Product-rajapinnan. Aiemmin mainitussa dokumenttiesimerkissä yksi sovellus voisi tukea monenlaisia dokumentteja; dokumentin tyyppi valittaisiin tehdasmetodille syötetyn parametrin perusteella. Normaalisti jokaista Product-luokkaa kohden kirjoitetaan Creator-luokan aliluokka. Tämän voi joskus välttää käyttämällä luokkamalleja. Ratkaisu onnistuu C++-kielessä ja Javan uudemmissa versioissa. 3. Prototype (Prototyyppi) Ohjelmaa laadittaessa voidaan kohdata tilanne, jossa luokan tulisi luoda olio, mutta luokka ei osaa tehdä tätä. Tämä voi sattua esimerkiksi laadittaessa graafista editoria, jolla lisätään dokumenttiin erityyppisiä olioita, joita käsitellään dokumentissa. Lisäämisestä vastaava luokka ei välttämättä osaa kuitenkaan luoda kaikkia tarvittavia olioita. Yksi ratkaisu tähän ongelmaan on soveltaa Prototype-suunnittelumallia: jokaisesta lisättävästä oliotyypistä on mallikappale, josta tehdään tarvittaessa kopio. Luotu kopio lisätään dokumenttiin. Suunnittelumallia voidaan käyttää kun järjestelmä ei saisi riippua siitä, miten sen tuottamat oliot luodaan ja kun jokin seuraavista ehdoista on voimassa: 1. Luotavan olion tyyppi määräytyy ajonaikaisesti, 2. Halutaan välttää Factory Method-suunnittelumallin tehdasluokkien rakennetta, 3. Luotavan luokan olioilla voi olla hyvin harvoja laillisia tiloja. Tällöin voi olla kätevämpää luoda olio kopioimalla kuin alustamalla suoraan. 4

Prototype-mallin luokkarakenne on seuraava Kuva 4. Prototype-mallin luokkakaavio (Vrt. [Gam]) Mallin osallistujat ovat Prototype, joka määrittelee luotavien olioiden rajapinnan. ConcretePrototype toteuttaa metodin itsensä kopioimiseksi. Client luo uusia olioita kutsumalla Prototype-luokan clone-metodia. Mallin perusidea on sama kuin Factory Method-mallissakin: on luotava olioita, joiden luomisen yksityiskohtia ei tunneta. Lisäksi Prototype-mallilla saavutetaan joitakin lisäetuja. Prototypemallilla saavutetaan yleensä yksinkertaisempi luokkarakenne kuin Factory Method-mallilla, koska olion luomiseen ei tarvita erillisiä luokkia. Lisäksi malli on joustavampi kuin Factory Method, koska uusia prototyyppejä voidaan tuoda ohjelmaan vaikka ajon aikana, riittää, että ne toteuttavat Prototype-rajapinnan. Lisäksi samasta luokasta voidaan tehdä useita prototyyppejä, joista voidaan luoda kopioita. Mallin suurin rajoitus on vaadittu rajapinta: kaikkien kopioitavien olioiden on toteutettava clonemetodi. Tämä voi olla vaikeata, jos yritetään soveltaa mallia luomaan jo olemassa olevan luokkarakenteen olioita. Mallin toteutuksen hankalin osa on clone-operaation toteuttaminen. Kloonattaessa on kuitenkin päätettävä, käytetäänkö pinta- vai syväkopiota. Pintakopiossa kopio-olioon kopioidaan sellaisenaan kopioitavan olion attribuuttien arvot. Tämä voi kuitenkin olla virheratkaisu, jos olio koostuu osoittimista varattuun muistiin tai dynaamisesti varattuihin olioihin. Java-kielessä olioihin viitataan aina viitetyyppisellä muuttujalla, joten Javassa ongelma tulee esiin aina koosteolioita käytettäessä. Näissä tapauksissa on mietittävä, pitääkö myös osaolioista tehdä kopiot uuden olion osaolioiksi, jolloin tehdään syväkopio. Pintakopiossa kopioitaisiin vain viitteet osaolioihin. Monissa kielissä on suora tuki olion kloonaamiseen. C++:ssa käytetään kopiomuodostinta, Javassa puolestaan kloonattavien olioiden on toteutettava Cloneable rajapinta, jolloin voidaan käyttää Object-luokan clone()-metodia. Se tekee oliosta pintakopion. 5

Joskus halutaan ohjelmassa kopio-oliosta ainoastaan tieto sen luokasta, jonka perusteella tehdään uusi olio oletusasetuksilla. Tällöin mallia voidaan laajentaa niin, että clone-operaation lisäksi Prototype-rajapintaa lisätään metodi create(), joka tuottaa aina oletusolion. 4. Singleton (Ainokainen) Joskus tarvitaan luokka, jonka instansseja voi kerrallaan olla olemassa korkeintaan yksi. Esimerkiksi ohjelmassa käytettyjen säiliöluokkien instanssien määrää voi olla hyvä rajoittaa yhteen. Kun olio on luotu, sen on myös syytä olla helposti saatavilla eri puolilla ohjelmaa. Globaalin muuttujan käyttäminen ei ole yleensä hyvä ratkaisu: on järkevämpää antaa luokan itsensä ratkaista ongelma. Luokka rajoittaa instanssinsa yhteen ja tarjoaa pääsyn ainoaan olioonsa. Tämä on Singleton-suunnittelumalli. Mallia siis sovelletaan tapauksiin, joissa on rajoitettava luokan instanssien lukumäärä yhteen ja luotu instanssi on saatava julkisen rajapinnan kautta. Luokka on voitava myös periä aliluokkiin niin, että luokan asiakkaiden ei tarvitse muuttaa koodiaan. Mallin luokkarakenne on yksinkertainen Kuva 5. Singleton-mallin luokkakaavio (Vrt. [Gam]) Luokkakaaviosta paljastuu, että luokan instanssi saadaan kutsumalla luokkakohtaista metodia getinstance. Tämä palauttaa luodun instanssin, jos instanssi on jo luotu. Jos instanssia ei ole vielä olemassa, se luodaan ja palautetaan. Olion suora luominen on myös estettävä, esimerkiksi kirjoittamalla sille private-tyyppinen muodostin, jotta olioita ei voi luoda luokan ulkopuolelta. Samoin on syytä yleensä estää myös olion kopioiminen, jotta luodusta oliosta ei voi tehdä uusia kopioita. C++-kielessä kopioinnin voi estää esittelemällä (private-tyyppinen) kopiointimuodostin, mutta jättämällä se toteuttamatta. 6

Mallin käytöllä saavutetaan monia etuja. Singleton-luokka voi kontrolloida muiden olioiden pääsyä instanssiinsa, koska se kapseloi instanssin sisäänsä. Mallia käytettäessä ei tarvita globaalia muuttujaa käyttämään Singleton-oliota: riittää, että luokan rajapinta on käytettävissä. Singleton-luokka voidaan myös periä ja käyttää aliluokkaa. Valinta voidaan tehdä ajonaikaisesti. Mallia voidaan myös helposti muokata niin, että luokan olioita voidaan luoda jokin muu kiinteä määrä kuin yksi. Lähteet [Gam] Gamma, Helm, Johnson, Vlissides: Design Patterns: Elements of Reusable Object- Oriented Software, Addison-Wesley 1995 7