TIE-11300 Tietotekniikan vaihtuva-alainen kurssi Graafisen käyttöliittymän ohjelmointi Syksy 2013 Luento 8 Suunnittelumallit käyttöliittymäohjelmoinnissa Juha-Matti Vanhatupa
Yleistä Suunnittelumalli on tunnettu ja käytännössä hyväksi havaitun ratkaisun kuvaus Käyttöönotto ei edellytä tiettyä teknologiaa, suunnittelumenetelmää tai ohjelmointikieltä Yksi 90-luvun ohjelmistosuunnitteluun eniten vaikuttaneista tekniikoista
Yleistä Suunnittelumalli koskee aina useita ohjelmayksiköitä, jotka järjestäytyneet tietyllä tavalla ratkaisussa. Määrittelee suhteet, jotka ratkaisuun kuuluvilla ohjelmayksiköillä on.
Keskeiset osat 1/3 Ongelma Yleinen suunnitteluongelma Ei edellytä tiettyä ohjelmointikieltä Tulee ilmetä toistuvasti monenlaisissa Järjestelmissä
Keskeiset osat 2/3 Ongelmayhteys Kertoo millaisissa tilanteissa suunnittelumalli on sovellettavissa Määrää myös ratkaisulle asetettavia vaatimuksia Vaatimukset liittyvät laatuominaisuuteen, jota ratkaisun tulee parantaa
Keskeiset osat 3/3 Ratkaisu Tulee olla yleinen ja oltava kuvattavissa yleisesti tunnetuilla formalismeillä (esim. UML:llä) Yleensä ratkaisu täyttää vaatimukset, mutta saattaa heikentää jotain toista laatuominaisuutta
Käyttöliittymäohjelmoinnissa käytettyjä suunnittelumalleja Tarkkailija Strategia Rekursiokooste MVC
Tarkkailija (Observer) Määrittelee olioiden välille yksi moneen riippuvuuden siten, että kun yhden olion tila muuttuu, siitä riippuvat oliot saavat ilmoituksen ja päivittyvät automaattisesti
Toteutustapoja QT Signaalien ja Slotien avulla.net eventtien avulla Java Rajapintojen avulla Observer, Observable
QT observer public class GUI { GUI(Subject* psubject); Subject* m_psubject; public slots: void onchanged(); }; GUI::GUI(Subject* psubject) { m_subject = psubject; connect(psubject,signal(changed()), this, SLOT(onChanged())); } void GUI::onChanged() { QString d = m_psubject->getdata(); } class Subject { public: QString getdata() const; void setdata(qstring data); signals: void changed(); private: QString m_data; }; QString Subject::getData() const { return m_data; } void Subject::setData(QString data) { m_data = data; emit changed(); }
Käyttö GUI-ohjelmoinnissa Model View ohjelmoinnin osana UI UI View1 View2 View3 Data Data Data
Käyttö GUI-ohjelmoinnissa QAbstractItemView* pview; QAbstractItemModel pmodel; pview->setmodel(pmodel); QAbstactItemModel { public: void insertrow(); void removerow(); signals: void datachanged(); void layoutchanged(); void modelreset(); void rowsinserted(); void rowsremoved(); int rowcount(); QModelIndex index(int row); QVariant data(qmodelindex & ind); }
Etuja Vähentää olioiden välisiä riippuvuuksia Selkeyttää ohjelman rakennetta Korvaa jatkuvat funktiokutsut, joissa tarkastetaan onko data muuttunut.
.NET observer public class GUI { public void GUI(Subject s) { s.changed += new EventHandler(update); } } public void update(object source, EventArgs e) { MessageBox.Show(s.Data); } public class Subject { private string data = ""; public event EventHandler Changed; } public string Data { get { return data; } set { data = value; // Informoidaan tarkkailijoita OnChanged(new EventArgs()); } }
Java observer public class GUI implements Observer { public void GUI(Subject s) { s.addobserver(this); } } public void update(observable o, Object arg) { String data = s.getdata(); } public class Subject extends Observable { private String data = ""; } public String getdata() { return data; } public void setdata(string d) { data = d; setchanged(); notifyobservers(); }
Strategia-suunnittelumalli Määrittelee algoritmiperheen, kapseloi kunkin algoritmin ja tekee niistä keskenään vaihdettavia. Algoritmia voidaan muuttaa muuttamatta sovellusta, joka sitä käyttää.
Strategia-suunnitelmamalli
Strategia-suunnittelumalli Käyttö GUI-ohjelmoinnissa Käytetään mm. valintaikkunoiden yhteydessä varmistamaan, että käyttäjä syöttää oikeanmallista tietoa. Esim. vaaditaan, että numeerinen tekstikenttä hyväksyy vain numeroita.
Esimerkki (Qt validator) QLineEdit* plineedit; // Hyväksy kokonaisluvut plineedit->setvalidator( new QIntValidator()); // Vaihda strategiaa ja hyväksy liukuluvut plineedit->setvalidator( new QDoubleValidator()); // Oma validaattori, joka hyväksyy email-osoitteen plineedit->setvalidator( new CEmailValidator());
QValidator Abstrakti rajapinta, joka sisältää 2 metodia State QValidator::validate ( QString & input, int & pos ) const [pure virtual] void QValidator::fixup ( QString & input ) const [virtual]
Strategia-suunnitelmalli (Qvalidator)
Rekursiokooste (Composite) Malli esittää oliot rekursiivisesti koostettuna puurakenteena. Yksittäisiä olioita ja oliokoosteita voidaan käsitellä samalla tavalla
Rekursiokooste
Rekursiokooste (Composite) Käyttö GUI-ohjelmoinnissa Käyttöliittymäikkunoiden yhteydessä QWidget* pcontainer = new QWidget(); pcontainer->setlayout(new QVBoxLayout()); QWiget* pbutton = new QPushButton(); pcontainer->layout()->addwiget(pbutton); QWiget* plabel = new QLabel(); pcontainer->layout()->addwiget(plabel); pcontainer->setenabled(false);
MVC Ohjelma tai jokin sen komponentti koostuu kolmesta osasta, joilla jokaisella on oma tehtävä. Model View Controller
MVC
MVC:n edut 1. Selkeä rakenne Malli ei ole riippuvainen näkymästä 2. Laajennettavuus Uusien näkymien luonti samalle mallille 3. Modulaarisuus Käyttöliittymäkoodin ja muun sovelluskoodin erottaminen toisistaan 4. Tuki hajautukselle
MVC:n haitat 1. Pienissä sovelluksissa lisää monimutkaisuutta 2. Puhtaan MVC-mallin noudattaminen käytännössä hankalaa johtuen UI-kirjastojen ominaisuuksista Esim QT:n model/view malli Päästäänkö lähes yhtä hyvään rakenteeseen yksinkertaisemmalla ratkaisulla?
MVC ja suunnittelumallit M C Tarkkailija Strategia V Rekursiokooste
Model Irroittaa käyttöliittymän ja datan Hyödyntää Tarkkailijasuunnittelumallia
View Esittää datan käyttäjälle Voi hyödyntää toteutuksessaan Rekursiokooste suunnittelumallia
Controller Käsittelee käyttäjän syötteet Voi hyödyntää Strategia-suunnittelumallia Kontrollerin vaihtaminen ajon aikana
MVC:n toteutustapoja Passiivinen malli Pull MVC Push MVC
Passiivinen malli MVC:n yksinkertaisimmissa toteutuksissa malli on täysin passiivinen
Pull MVC Malli informoi kuuntelijoita, kun sen tila muuttuu. Tämän jälkeen näkymä kysyy mallilta muuttuneen datan ja päivittää käyttöliittymän uuden tilan mukaiseksi. Notify View Get data Return data Model
Push MVC Malli informoi kuuntelijoita, kun sen tila muuttuu. Muuttunut data lähetetään parametrina kutsun yhteydessä. View Notify (Data modified) update Model