T Henkilökohtainen harjoitus: FASTAXON

Samankaltaiset tiedostot
Rinnakkaisohjelmointi kurssi. Opintopiiri työskentelyn raportti

Olio-ohjelmointi Javalla

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

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Projekti 1 Säikeet ja kriittisen vaiheen kontrollointi javalla

Rajapinta (interface)

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

Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä

Listarakenne (ArrayList-luokka)

14. Poikkeukset 14.1

14. Poikkeukset 14.1

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

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

Mikä yhteyssuhde on?

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

Ohjelmistotekniikan menetelmät, suunnittelumalleja

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

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

TIETORAKENTEET JA ALGORITMIT

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

Java kahdessa tunnissa. Jyry Suvilehto

812341A Olio-ohjelmointi Peruskäsitteet jatkoa

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

1 Tehtävän kuvaus ja analysointi

Luento 6. T Ohjelmoinnin jatkokurssi T1 & T Ohjelmoinnin jatkokurssi L1. Luennoitsija: Otto Seppälä

Javan semaforit. Joel Rybicki, Aleksi Nur mi, Jara Uitto. Helsingin yliopisto

Java-API, rajapinnat, poikkeukset, UML,...

Ohjelmoinnin jatkokurssi, kurssikoe

15. Ohjelmoinnin tekniikkaa 15.1

Javan perusteita. Janne Käki

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

Kompositio. Mikä komposition on? Kompositio vs. yhteyssuhde Kompositio Javalla Konstruktorit set-ja get-metodit tostring-metodi Pääohjelma

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Taulukot & Periytyminen

7. Näytölle tulostaminen 7.1

Ohjelmointi 2 / 2008 Välikoe / Pöytätestaa seuraava ohjelma.

Liite 1. Projektin tulokset (Semaforit Javassa) Jukka Hyvärinen Aleksanteri Aaltonen

15. Ohjelmoinnin tekniikkaa 15.1

Monitorit -projekti Rinnakkaisohjelmointi

Suunnittelumalleja, MVC. Juha Järvensivu 2008

Ohjelmointi 2 / 2010 Välikoe / 26.3

Pino S on abstrakti tietotyyppi, jolla on ainakin perusmetodit:

Metodien tekeminen Javalla

10 Lock Lock-lause

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

P e d a c o d e ohjelmointikoulutus verkossa

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

Poikkeustenkäsittely

Informaatioteknologian laitos Olio-ohjelmoinnin perusteet / Salo

KOHDELUOKAN MÄÄRITTELY

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

1. Mitä tehdään ensiksi?

Luokan sisällä on lista

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä. Tiedonkätkentä. Aksessorit. 4.2

SEPA - Design Patterns

Luokka Murtoluku uudelleen. Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista.

Luokan muodostimet (Constructors)

Vertailulauseet. Ehtolausekkeet. Vertailulauseet. Vertailulauseet. if-lauseke. if-lauseke. Javan perusteet 2004

Kääreluokat (oppikirjan luku 9.4) (Wrapper-classes)

Hirviö. Design Patterns

Olio-ohjelmointi Virhetilanteiden käsittely

Tietorakenteet, laskuharjoitus 7,

Ohjelmoinnin perusteet, kurssikoe

16. Javan omat luokat 16.1

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

9. Periytyminen Javassa 9.1

Muusta kuin vesisioista

Java-kielen perusteet

Sisällys. 1. Omat operaatiot. Yleistä operaatioista. Yleistä operaatioista

Lista luokan sisällä

Jaana Diakite Projekti 1 JAVA-Monitorit 1(13) Rinnakkaisohjelmointi Anu Uusitalo

12. Javan toistorakenteet 12.1

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä ja ulkopuolelta. Attribuuttien arvojen käsittely aksessoreilla. 4.2

SEPA REFAKTOROINTI Antti Ahvenlampi, 57408L Erik Hakala, 57509T

ITKP102 Ohjelmointi 1 (6 op)

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. X Poikkeusten käsittelystä

Periytyminen (inheritance)

Semaforit Javassa. Mari Kononow, Eveliina Mattila, Sindi Poikolainen HELSINGIN YLIOPISTO

1. Omat operaatiot 1.1

Metodit Arvotyyppi. Metodit Arvotyyppi. Metodit Parametrit. Metodit Parametrit. Metodit Kuormittaminen. Metodit Kuormittaminen. Javan perusteet

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

4. Olio-ohjelmoinista lyhyesti 4.1

12. Javan toistorakenteet 12.1

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

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Tietorakenneluokkia 2: HashMap, TreeMap

List-luokan soveltamista. Listaan lisääminen Listan läpikäynti Listasta etsiminen Listan sisällön muuttaminen Listasta poistaminen Listan kopioiminen

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

Tietorakenteet. JAVA-OHJELMOINTI Osa 5: Tietorakenteita. Sisällys. Merkkijonot (String) Luokka String. Metodeja (public)

Ohjelmointi 2 / 2011 Välikoe / 25.3

Ohjelmistojen mallintaminen, suunnittelumalleja

Rinnakkaisohjelmointi, Syksy 2006

5/20: Algoritmirakenteita III

11. Javan toistorakenteet 11.1

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

20. Javan omat luokat 20.1

9. Periytyminen Javassa 9.1

Taulukot. Jukka Harju, Jukka Juslin

Sisällys. 20. Javan omat luokat. Java API. Pakkaukset. java\lang

7. Oliot ja viitteet 7.1

Transkriptio:

T-76.115 Henkilökohtainen harjoitus: FASTAXON Suunnittelumallit Group: Muuntaja Pentti Vänskä 52572W

2 1. Toteutus Tämä henkilökohtainen harjoitustyö käsitteli suunnittelumallien (Design Patterns) käyttöä Fastaxon-projektissa. Suunnittelumalleja pyrittiin soveltamaan, mikäli niiden käyttö näytti olevan projektin kannalta hyödyllistä. Suunnittelumalleja ei yritetty soveltaa väkisin tämän projektin ongelmiin. Käytännössä suunnittelumallien käyttö rajoittui koodin malliosaan (Model). Tässä dokumentissa esitellään ne suunnittelumallit, jotka tulivat tietoisesti malliin mukaan. Koodista voi hyvin löytää paljon muita suunnittelumalleja, joita ei tässä dokumentissa esitellä. 2. Suunnittelumallien jaottelu Suunnittelumallit jaetaan käyttötarkoituksen mukaan kolmeen päätyyppiin, jotka ovat seuraavia [1, s.10; 3, 12]: 1. creational 2. structural 3. behavioral Creational-mallit ovat objektien luomiseen liittyviä malleja. Näiden mallien avulla objektien luominen tavallaan automatisoidaan. Structural-malleja käytetään luotaessa olioita suuremmiksi kokonaisuuksiksi. Behavioral-mallit on tehty helpottamaan objektien välistä kommunikointia. Tässä dokumentissa esitellään jaottelun mukaisesti seuraavat suunnittelumallit: 1. creational-mallit singleton abstract factory 2. structural-mallit façade proxy 3. behavioral-mallit command pattern 3. Mallien käyttö Fastaxon-projektissa Kaikki mallit on otettu käyttöön projektin I2 ja I3-vaiheissa. Tässä dokumentissa esiteltävät mallit ovat edelleen käytössä. Fastaxonprojektissa on sovellettu Model View Controller - arkkitehtuuria, jossa siis ohjelma jaetaan kolmeen pääosaan: malliin, näyttökomponentteihin ja niitä yhdistävään kontrolleriin. Tätä arkkitehtuuria voidaan sinällään pitää jo yhtenä suunnittelumallina. 2

3 Singleton Singleton-suunnittelumallin avulla tietystä luokasta luodaan vain yksi instanssi hallitusti [1, s. 127; 2 s. 31]. Projektin mallissa (model) ModelContext on singleton-tyyppinen luokka. Luokan ainoa instanssi saadaan getinstance-metodin avulla. Tämä luokan kautta kaikki mallin muut oliot luodaan, siksi juuri singleton on tähän sopiva. Vastaavasti myös mallin DBPool on singleton-tyyppinen luokka. Myös tämän luokan ainoa instanssi saadaan getintance-metodilla. DBPool-luokan kautta saadaan tietokantayhteyksien määrä pidettyä tietyssä rajassa. Luokassa luodaan tietty määrä DBHelper-olioita, joista yksi edustaa yhtä yhteyttä. Luokan DBPool getinstance-metodin koodi näyttää seuraavalta: public synchronized static DBPool getinstance() throws DatabaseException { if (instance == null) { int max = Integer.parseInt((String) ModelContext.getInstance().getParametres().get(MAX_CONNECTIONS)); instance = new DBPool(); helpers = new Stack(); boolean standalone = false; if (ModelContext.getInstance().getParametres().get(STANDALONE).equals("true")) { standalone = true; for (int i = 0; i < max; i++) { helpers.push(new DBHelper(standalone)); catch(modelexception e){ throw new DatabaseException(e); return instance; Kuten koodista huomataan, luodaan DBPool-luokan instanssi, jos sitä edustava instance-kentän arvo on null. Intance-kenttä on tyypiltään staattinen eli kenttämääritys on seuraava: private static DBPool instance = null; DBHelpers-oliot talletetaan pinoon, josta niitä jaetaan tarpeen mukaan gethelper-metodilla, jonka koodi näyttää seuraavalta: public synchronized DBHelper gethelper() throws DatabaseException { while (helpers.isempty()) { wait(); catch (InterruptedException e) { throw new DatabaseException(e); return (DBHelper) helpers.pop(); Koodista voidaan havaita, että kutsuva säie (engl. thread) asetetetaan wait-tilaan wait-metodin avulla eli tällöin säikeen suoritus pysähtyy, 3

4 jos DBHelper-olioiden pino helpers on tyhjä. Käytännössä tilanne, jolloin pino on tyhjä, tarkoittaa se sitä, että maksimimäärä tietokantayhteyksiä on käytössä. Wait-tilassa olevat tietokantayhteydet vapautuvat, kun wait-tilassa oleva säie saa notifymetodilla jatkamiskäskyn (=säie herätetään), jolloin kyseinen säie jatkaa while-silmukassa suoritusta, jossa tarkistetaan onko helpersolioiden pino edelleen tyhjä. Jos pino ei ole, tyhjä palauttaa gethelper-metodi helpers-pinosta DBHelper-olion. Säie saa notifymetodilla jatkamiskäskyn metodissa releasehelper, jonka koodi näyttää seuraavalta: public synchronized void releasehelper(dbhelper helper) { helpers.push(helper); notify(); Mallissa releasehelper-metodia kutsutaan sen jälkeen, kun kutsuva säie ei enää tarvitse tietokantayhteyttä. Javassa on käytössä ns. signal and continue -tyyppinen moniajosysteemi, johon kaikki edellä esitetty periaatteessa perustuu. Singleton-suunnittelumallin käyttö on tässä yhteydessä hyvin perusteltua, jotta yhteyksien jakaminen ja vapauttaminen tapahtuisi hallitusti. Tälle suunnittelumallille on vaikea keksiä vaihtoehtoista mallia, ja siitä on lähes korvaamaton hyöty tässä projektissa. Abstract factory Abstract factory -suunnittelumallin avulla tuotetaan olioita annetun syöttötiedon perusteella. Erona pelkkään Factory-sunnittelumalliin on se, että tässä suunnittelumallissa olioiden toteuttavat luokat piilotetaan ja ne voidaan tarvittaessa vaihtaa [1, s.87; 2 s. 26]. Projektin mallissa (model) rajapinnat ja niiden toteuttavat luokat on talletattu ModelContext-luokan parametritietoihin siten, että kunkin rajapinnan toteuttava luokka on haettavissa. Metodilla setparametres asetetaan mallin parametrit HashMap-oliona. Metodi getmodelfactory palauttaa mallin ModelFactory-rajapinnan toteuttavan olion. Metodin javakoodi näyttää seuraavalta: public synchronized ModelFactory getmodelfactory() throws ModelException { if (factory == null) { String implclassname = (String) getparametres().get("fi.vtt.fastaxon.model.interfaces.modelfactory"); Class implclass = Class.forName(implClassName); factory = (ModelFactory) implclass.newinstance(); catch (Exception e) { throw new ModelException(e); return factory; 4

5 Vastaavaan tapaan muut mallin rajapintojen oliot luodaan ModelFactory-luokan getmodel-metodeilla, joka palauttaa halutun olion annettujen parametritietojen avulla. Metodista on kolme ylikuormitettua versiota eri käyttötapauksia varten. Metodin javakoodi näyttää seuraavalta: public Object getmodel(string modelinterfaceclassname, Object[] parametres) throws ModelException { Object model = null; boolean cacheable = false; ModelContext context = ModelContext.getInstance(); String classimpl = (String) context.getparametres().get(modelinterfaceclassname); Class modelclass = Class.forName(classImpl); if (iscacheable(modelclass)) { cacheable = true; model = getcache().getmodel(modelinterfaceclassname, parametres); if (model!= null) return model; Constructor constr[] = modelclass.getconstructors(); for (int i = 0; i < constr.length; i++) { model = constr[i].newinstance(parametres); if (model!= null) break; catch (Exception e) { catch (ClassNotFoundException e) { throw new ModelException(e); if (model == null) throw new ModelException(EXP_CANNOT_GET_MODEL, "get model"); if (cacheable) getcache().addmodel(modelinterfaceclassname, parametres, model); return model; Koodin perusideana on Class-luokan metodit, joiden avulla rajapinnan toteuttavan luokan Class-olio saadaan luotua. Kyseisen luokan sopivalla konstruktorilla luodaan annetun parametritaulukon avulla itse luokan instanssi. Tässä koodissa on lisäksi mukana kätkömuistin käsittely, joka tuo muutaman rivin tähän lisää. Lopputuloksena saadaan aikaan järjestely, jossa haluttu olio saadaan seuraavaan esimerkin tapaan: Facet facet = (Facet)modelContext.getModelFactory().getModel("fi.vtt.fastaxon.model.interfaces.Facet", parametres); Parametreina annetaan siis rajapinnan String-olio sekä Objecttyyppinen taulukko, joka sisältää konstruktorin tarvitsemat parametrit. Tämän suunnittelumallin hyöty on suuri tässä projektissa. Tälle suunnittelumallille vaihtoehtona voisi olla esimerkiksi sellainen malli, jossa oliot luodaan suoraan new-operaattorilla. Tämä malli ei kylläkään ole vaihtoehtoinen suunnittelumalli. 5

6 Façade Façade-suunnittelumallin avulla monimutkaisen oliomallin käyttöä pyritään helpottamaan siten, että mallin käyttäminen yksinkertaistetaan tekemällä erityinen luokka, jonka kautta oliomallia käytetään [1 s. 185; 2 s. 111]. Projektin mallin ModelContext luokkaa voidaan pitää façadesuunnittelumallin mukaisena edustaluokkana. ModelContext-luokan kautta saadaan Designer-olio, jonka kautta saadaan suunnittelijan Context-olio, jolla on päästään käsiksi ko. suunnittelijan projekteihin. Malliin oli tarkoituksena toteuttaa sellainen esto, jolla estettäisiin new-operaattorin käyttö rajapintojen toteuttaviin luokkiin. Tämä esto ei kuitenkaan toimi nyt, koska luokkien konstruktorit ovat publictyyppisiä. Tällä estolla oliomallin väärin käyttö olisi mahdotonta. Tästä suunnittelumallista on varsin suuri hyöty, koska sen avulla oliomallin käyttäminen on helpompaa. Vaihtoehtoisesti oliomallia voisi käyttää suoraan ilman ohjaavaa luokkaa. Proxy Proxy-suunnittelumallin avulla luodaan aikaiseksi sellainen järjestely, jossa varsinaisen käyttöolion taakse piilotetaan suorittavaolio tai olioita, joilla on oma tarkoituksen mukainen tehtävä. Tätä suunnittelumalli on käyttökelpoinen esimerkiksi seuraavissa tilanteissa [1 s. 207; 2 s. 124]: 1. oliossa on toiminto, jonka suorittaminen vie paljon aikaa 2. erilaisten oikeuksien jakaminen olioiden välillä Projektin mallissa kaikki mallin rajapintojen toteuttavat luokat ovat periaatteessa proxy-suunnittelumallin tyyppisiä luokkia. Toteuttavissa luokissa on paljon sellaisia metodeja, joita ei ole määritelty rajapinnoissa. Toteuttavat luokat kutsuvat myös DBHelper-luokan metodeja eli osa luokkien toiminnasta on eriytetty toiseen luokkaan. Nämä DBHelper-luokan metodit on suojattu niin, että niitä ei voi käyttää paketin ulkopuolelta. Tämä suunnittelumalli on varsin hyödyllinen oliomallin kannalta. Vaihtoehtoisesti kaikki luokan toiminta voisi olla samassa yhdessä luokassa. Command pattern Command pattern -suunnittelumallin ideana on luoda mahdollisuus olioiden väliseen kommunikointiin tietyllä sovitulla tavalla [1 s. 233; 2, s.139]. 6

7 Projektin mallissa on rajapinta Model, jossa on määritelty metodit, joilla mallin olioiden välinen tiedonvälitys on mahdollista järjestää. Käytännössä mikä tahansa olio voi kuunnella toista oliota ja saada tältä viestejä. Rajapinnan metodit ovat seuraavia: - addmodellistener - removemodellistener - notifymodellisteners - modelchanged Tässä Command pattern -suunnittelumallin käyttö on tarkemmin vain metodissa modelchanged, jota kutsutaan olion muutostilanteessa. Muilla metodeilla luodaan systeemi, jossa olioon voidaan liittää kuuntelija addmodellistener-metodilla, poistaa kuuntelija removelistener-metodilla sekä viestittää kuuntelijoita notifymodellisteners. Lisäksi systeemissä on ModelEvent-luokka, joka on sisältää kaiken viestitettävän informaation. Metodi notifymodellisteners välittää ModelEvent-olion rekursiivisesti kaikille olion kuuntelijoille. Koodi näyttää seuraavalta: public synchronized void notifymodellisteners(modelevent modelevent) throws ModelException { if (modelevent.getmodel() == null) modelevent.setmodel(this); recursemodels(modelevent); protected void recursemodels(modelevent modelevent) throws ModelException { Iterator iterator = getlisteners().values().iterator(); while (iterator.hasnext()) { Model model = (Model) iterator.next(); modelevent.setsender(this); model.modelchanged(modelevent); ((ModelImpl) model).recursemodels(modelevent); Tämän mallin hyöty jäi varsin vähäiseksi, koska projektin aika alkoi käydä vähiin ja mallia ei ehditty soveltamaan kunnolla. Vaihtoehtoisesti oliomallissa voisi olla sellainen systeemi, jossa kussakin luokassa olisi tietyt ylläpitometodit (esimerkiksi remove ja update metodit) Command -mallin tapaan. Itse asiassa kysymyksessä olisi tämän saman suunnittelumallin toisenlainen toteutus. 7

8 LÄHTEET 1. Gamma Eric, Helm Richard, Johnson Ralph, Vlissides John, Design Patterns 2. Cooper James W., The Design Patterns Java Companion 8