Liigu peamise sisu juurde

Sissejuhatus disainimustritesse

Sissejuhatus

Programmide kasvades hakkavad ühed ja samad probleemid üha uuesti esile kerkima: kuidas luua objekte paindlikult, kuidas võimaldada objektide vahelist suhtlust ilma neid liiga tihedalt sidumata ning kuidas korraldada koodi nii, et uue funktsionaalsuse lisamine ei nõuaks olemasoleva ümberkirjutamist.

Paljud neist probleemidest on erinevate inimeste poolt erinevates programmides korduvalt lahendatud. Aja jooksul hakkas nende lahenduste kuju ühtlustuma. Ilmnesid sarnased klasside ülesehitused, sarnased vastutuste jaotused ning sarnased kompromissid. Selliseid korduvaid tüüplahendusi nimetatakse disainimustriteks.

Disainimuster ei ole konkreetne koodilõik, mida saab lihtsalt kopeerida. Disainimustrid kirjeldavad mõnda kindlat lahendust ehk millised klassid on üksteisega seotud, kuidas need omavahel suhestuvad ning millist probleemi selline ülesehitus lahendab. Sama mustrit saab rakendada mitmel erineval viisil, sõltuvalt programmeerimiskeelest ja konkreetsest olukorrast.

Gang of Four

Mõiste „disainimuster“ objektorienteeritud programmeerimise kontekstis pärineb 1994. aastal ilmunud raamatust "Design Patterns: Elements of Reusable Object-Oriented Software", mille autorid on: Erich Gamma, Richard Helm, Ralph Johnson ja John Vlissides. Neid nelja autorit tuntakse ühiselt Gang of Four (GoF) nime all.

Raamat kirjeldab 23 disainimustrit ning jaotab need kolme kategooriasse vastavalt lahendatava probleemi tüübile:

  • Loomismustrid (creational patterns) - kuidas objekte luuakse.
  • Struktuurimustrid (structural patterns) - kuidas objekte ühendatakse suuremateks tervikuteks.
  • Käitumismustrid (behavioural patterns) - kuidas objektid suhtlevad ja vastutust jagavad.

Järgmised peatükid keskenduvad loomismustritele. Struktuuri- ja käitumismustreid käsitletakse hiljem.

Loovmustrid

Programmid on täis new SomeClass(...) väljakutseid ning enamasti on see täiesti sobiv lahendus. Kuid on olukordi, kus otsene new kasutamine tekitab probleeme, näiteks:

  • Loodav klass ei ole teada enne käitusaega.
  • Objekti loomine on kulukas ning soovime olemasolevaid isendeid taaskasutada.
  • Konstruktoril on liiga palju parameetreid, mis muudab koodi raskesti loetavaks.
  • On vaja tagada, et klassist eksisteeriks ainult üksainus isend.
  • Soovime objekti kopeerida, teadmata selle täpset tüüpi.

Nende probleemidega tegelemiseks on välja mõeldud loovmustrid - iga loovmuster lahendab ühe sellise olukorra. Neid kõiki ühendab ühine eesmärk: eraldada objekti kasutav kood sellest koodist, mis otsustab, kuidas objekt luuakse. Tulemuseks on kood, mida on lihtsam laiendada, testida ja mõista.

Selles jaotises käsitleme järgmiseid mustreid:

  • Factory - üks keskne koht, mis otsustab, milline klass instantsitakse.
  • Factory Method - laseb alamklassidel otsustada, milline klass luuakse.
  • Abstract Factory - loob terveid omavahel sobivate objektide perekondi.
  • Builder - võimaldab keerukaid objekte samm-sammult koostada.
  • Singleton - tagab, et klassil on ainult üks isend.
  • Prototype - loob uusi objekte olemasolevaid kopeerides.

Mustritest üldisemalt

Disainimustrite tundmine on tähtis, kuid nende lisamine koodibaasi ei peaks omaette eesmärk olema. Mõte ei ole kasutada võimalikult palju mustreid, vaid ära tunda olukorda, kus sinu ees olev probleem vastab mõne tuntud lahenduse kujule.

Õigesti kasutatuna muudavad mustrid koodi selgemaks, sest kogenud lugeja tunneb need kiiresti ära. Valesti kasutatuna lisavad need aga tarbetuid vahekihte, mis peidavad lihtsa loogika liigse vormilisuse taha. Järgmisi peatükke lugedes pööra tähelepanu mitte ainult sellele, mida iga muster teeb, vaid ka sellele, millal seda on mõistlik kasutada.