582101 - Ohjelmistotekniikan menetelmät, suunnittelumalleja 1
Suunnittelumallit (design patterns) Kuvaus sellaisesta luokkarakenteesta & olioiden vuorovaikutuksesta, joka ratkaisee tietyn yleisen ongelman tiettyjen reunaehtojen vallitessa Keskeinen lähde suunnittelumalleihin Gamma et al., Design Patterns Elements of Reusable Object-Oriented Software, Addison-Wesley, 1995 2
Ongelma kontekstissaan Gamma & al. dokumentoivat suunnittelumallinsa dokumentoidaan standardoidussa formaatissa: 1. Nimi 2. Ongelmakuvaus 3. Ratkaisu 4. Seuraukset Mallit ovat sidottuja johonkin ympäristöön Ei-olioympäristössä voisivat oliomaaliman peruskäsitteet perintä, kapselointi ja polymorfismi olla omia suunnittelumallejaan 3
Mallien luokittelu Gamma et al. jaoittelevat mallinsa kolmeen pääkategoriaan 1. Olioiden luontimallit (creational) 2. Olioiden käyttäytymismallit (behavioral) 3. Luokkien rakenteelliset mallit (structural) Mallien tunteminen ja käyttäminen helpottaa kommunikaatiota suunnittelijoiden välillä Yhteinen sanasto Ohjelmakoodia korkeampi abstraktion taso 4
Luokkien ilmentymien luonti Kuka kutsuu luokan konstruktoria uuden ilmentymän luomiseksi? Koska ilmentymiä pitäisi luoda? jotkut oliot luodaan ohjelman käynnistyessä main- tai alustusoperaatiossa monet oliot luodaan dynaamisesti suoritusaikana, mutta niiden luoja on tiedossa staattisesti (käännösaikana) joissain tapauksissa olion luoja määräytyy dynaamisesti vasta suoritusaikana 5
Luontimalli new() Yksinkertaisin, ja kaikkien monimutkaisempien luontimallien hyödyntämä olion luontitapa on käyttää kielen new-avainsanaa: new Kirahvi(); new-avainsanaa käyttäessä kiinnitetään se konkreettinen luokka, josta olio halutaan instantioida Tämä vaikeuttaa geneeristen, uudelleenkäytettävien ohjelmien tekemistä Luontimalleja: abstrakti tehdas, rakentaja, tehdasmetodi, prototyyppi, ainokainen 6
Luontimalli tehdasmetodi (factory method) Määritellään luokkaan metodi, jonka tehtävä on luoda halutunlaisia olioita. Merkitys 1 (puhtaampi oliotapa) Aliluokka kiinnittää luotavan olion tyypin syrjäyttämällä yliluokan metodin Merkitys 2 (yleisempi) Metodi jollain keinoin päättää, minkä luokan olio instantioidaan 7
Esimerkki tehdasmetodista public static Frequency getfrequency(double d) { Frequency f; if(testing) { f = new MockFrequency(d); else { f = new ObservableFrequency(d); return f; Miten kääntäisitte tämän puhtaammaksi oliotehdasmetodiksi? 8
Luontimalli abstrakti tehdas Erilaisten, yhteenkuuluvien olioperheiden tuottamiseksi sopii luontimalli abstrakti tehdas Abstrakti rajapinta yhteenkuuluvien olioiden luomiseksi kiinnittämättä niiden konkreettisia luokkia Mahdollistaa sovelluksen konfiguroimisen luomaan tietyn konkreettisten aliluokkien perheen ilmentymiä 9
Abstrakti tehdas UML:nä Client AbstractFactory createproducta() createproductb() ConcreteProductA1 AbstractProductA ConcreteProductA2 ConcreteFactory2 ConcreteFactory1 AbstractProductB createproducta() createproductb() createproducta() createproductb() ConcreteProductB1 ConcreteProductB2 10
Olioiden käyttäytymismallit Olioiden ajonaikaisen käyttäytymisen mallintaminen Käyttäytymismalleilla tyypillisesti pyritään parantamaan järjestelmän joustavuutta mahdollistamalla käyttäytymisen parametrointi ja/tai yksityiskohtien piilottaminen Malleja esim. vastuuketju, iteraattori, hiutale, operaatiorunko, vierailija,.. (Chain of responsibility, Iterator, Flyweight, Template method, Visitor).. 11
Iteraattori Iteraattorilla erotellaan oliokokoelman sisäinen rakenne ja kokoelman läpikäymisen logiikka toisistaan Käyttö hyvin yksinkertaista: List<Radio> radios = new ArrayList<Radio>();. for(radio r : radios) { print ( r ); Iterointirajapinnan tarjoaminen ns. asiakaspalvelua 12
Operaatiorunko (template method) Määritellään operaatiolle yleinen runko, yksityiskohdat vaihtelevat olioverkon konfiguraation mukaan 13
Operaatiorunko checkfrequency() protected boolean checkfrequency(int frequency) { int nextstep = 0; while(nextstep < 1000) { if(!checkfrequency(frequency, nextstep)) { return false; nextstep += 25; return true; checkfrequency(int, int) antaa variaatiopisteen operaatiorungolle 14
Vastuuketju (chain of responsibility) Erotetaan palvelupyynnön lähettäjä palvelun toteuttajasta antamalla useammalle oliolle mahdollisuus huolehtia palvelun toteutuksesta Toteuttaja delegoi palvelupyynnön ketjussa seuraavalle, jos se ei itse pysty toteuttamaan palvelua (kokonaan) Client Handler handlerequest() successor ConcreteHandler1 handlerequest() ConcreteHandler2 handlerequest() 15
Radiotarkistuksen vastuketju public boolean check() { for(radio radio : radios) { if(!radio.check()) { return false; return true; 16
Rakennemallit Rakennemallit käsittelevät tapoja järjestää luokka- ja oliorakenteita Esim. sovitin (adapter), hiutale (flyweight), edustaja (proxy), silta (bridge), rekursiokooste (composition), 17
Sovitin Olemassaolevaa luokkarakennetta uudelleenkäytettäessä rajapinnat eivät aina ole yhteensopivia Sovitin-mallilla rajapintojen väliin sijoitetaan.. sovitin Ks. tämän viikon tehtävät, 1 18
Hiutale (flyweight) Hiutale-mallilla yhdistetään samanlaisia tai samankaltaisia olioita muistin säästämiseksi Esim. tekstinkäsittelyjärjestelmässä jokainen yksittäinen kirjain Sivuvaikutuksena samankaltaiset oliot voivat myös toimia kommunikaatioyhteyksinä 19
Frequency-flyweight public static Frequency getfrequency(double d) { Frequency f = frequencycache.get(d); if(f == null) { f = new MockFrequency(d); frequencycache.put(d, f); return f; 20
Yhteenvetona Nyt läpikäytiin vain muutamia yleisesti esiintyviä suunnittelumalleja, hyvin yleisellä tasolla Mallien käyttö on monesti eri mallien koostamista ja yhteensovittamista Esim. Flyweight + Factory method 21