Objektno orijentisano dizajniranje

Programiranje pomoću objekata kao rezultat dalo je potpuno novi način razmišljanja o dizajniranju softverskih sistema. Nove tehnike za dizajniranje sistema unutar objektno-orijentisane paradigme su izašle
na videlo. Možda ćete poželeti da dizajnirate svoj sledeći projekat pomoću ovih tehnika.

Kao što je proceduralna paradigma kao rezultat dala više različitih metoda za dizajniranje sistema pomoću tehnika strukturnog programiranja, tako i objektno orijentisana paradigma nudi više različitih filozofija dizajniranja.

Da bi efikasno dizajnirali softverski sistem, moramo da imamo jasnu predstavu o softveru i njegovom unutrašnjem funkcionisanju. Ovo važi bez obzira koju filozofiju dizajniranja izaberemo. To
komplikovano znanje je čak veoma važno kada dizajnirate objektno-orijentisani sistem.
Dobro dizajnirani objekti i hijerarhije klasa zahtevaju da relacije između različitih objekata budu dobro shvaćene.

Razvojni proces objektno-orijentisanog dizajniranja se dosta razlikuje od tradicionalnih „top-down” ili strukturiranih tehnika dizajniranja.
Naglasak je na stvarnim entitetima iz realnog sveta koje softverski sistem teži da emulira.
Pored toga, objektno orijentisane tehnike omogućavaju da se softver razvija u iterativnim ciklusima čime omogućava da se razviju prototipski sistemi i testiraju u ranoj fazi. To je velika prednost u odnosu na tradicionalne tehnike, kod kojih se prvi prototip mogao razviti tek u završnoj fazi procesa razvoja.

Sledeći spisak služi kao kratak pregled aktivnosti kod objektno orijentisanog dizajniranja:

  • Domen problema
    • Identifikovanje entiteta iz realnog sveta
    • Identifikovanje barijera entiteta.
    • Identifikovanje relacija između entiteta tj, identifikovanje klasa entiteta
  • Modelovanje
    • Kreiranje modela entiteta i modela klasa entiteta
  • Implementacija
    • Implementiranje (realizacija) klasa i sistema
  • Optimizovanje koda
  • Testiranje sistema

Prethodne aktivnosti se ne moraju obaviti u navedenom redosledu, što se u praksi najčešće i dešava. Aktivnosti se obavljaju po sistemu napred-nazad, ponekad paralelno a često i u više iteracija. Suština
objektno-orijentisanog dizajniranja je da više puta prođete kroz ceo ciklus, kreirate prototipske implementacije, testirate i uklanjate greške. Često, testiranje identifikuje oblasti koje je potrebno ponovo dizajnirati.
Pošto su klase samostalni entiteti to je dosta lako napraviti izmene u implementaciji uz minimalan uticaj na
ostatak sistema (pri tome se sam algoritam programa uopste ne menja).

Objektno-orijentisane karakteristike C++

Naš primarni cilj je da ustanovimo kakvu podršku ima C++ za fundamentalne karakteristike objektno-orijentisane paradigme: inkapsulaciju, nasleđivanje i polimorfizam, kao i tehnike kojima jezik C++ ovo realizuje.
C++ uvodi mehanizam klase koji ne samo da obezbeđuje sposobnost za dizajniranje i implementiranje apstraktnih tipova podataka, već obezbeđuje i osnove za objektnu orijentaciju.

INKAPSULACIJA u C++.

C++ proširuje C sposobnošću za definisanje novih tipova podataka. Klasa je kao C struktura, ali sadrži i podatke i metode. Pored toga, C++ obezbeđuje različite nivoe pristupa članovima klase kako bi kontrolisao kako može da se manipuliše njima izvan klase.

Važnost apstrakcije podataka je u sakrivanju detalja implementacije objekta-podatka od korisnika. Korisnik pristupa objektu samo preko njegovog JAVNOG INTERFEJSA.
C++ klasa sastoji se od javnog i privatnog dela.
Javni deo obezbeđuje interfejs za korisnike klase, dok privatni deo mogu da koriste samo funkcije koje su članice klase.

C++ obezbeđuje službene reči koje se koriste za označavanje koji članovi klase su skriveni a koji su deo njenog javnog interfejsa.
Članovi skrivene implementacije su markirani službenom reči keyword na početku sekcija.
Javni deo interfejsa klase sledi posle službene reči public.
Podrazumeva se da su deklaracije unutar klase privatne, što znači da samo funkcije-članice (i prijatelji) klase imaju pristup njima.

Pogledajmo sada jednu C++ definiciju klase (IArray).
Vidimo da su podaci-članovi DefaultSize, size i funkcija-član Init() privatni i stoga nedostupni korisnikovim
programima.
Postoji samo jedna funkcija-član unutar javne sekcije definicije klase IArray.
Ove funkcije se sastoje od podrazumevanog konstruktora; kopije konstruktora; destruktora; operatora
dodeljivanja, indeksiranja i izlaza, kao i funkcije koja vraća veličinu niza.

//Definicija klase
#ifndef IARRAY_DEF
#define IARRAY_DEF
 
    class IArray {
        private:
            enum {DefaultSize = 12};
            // Interna reprezentacija
            int size;
            int *data;
 
            void Init (const int* d, int s);
 
        public:
            // Podrazumevani (default) konstruktor
            IArray (int sz = DefaultSize);
            // Još jedan korisni konstruktor
            IArray (const int* d, int sz);
            //Konstruktor kopije
            IArray (const IArray& ia);
            // Destruktor
            ~IArray ();
 
            // Operator dodeljivanja
            IArray& operator= (const IArray& a);
            // Operator indeksiranja
            int& operator[] (int index);
 
            // Veličina
            int Size() const;
 
            // Operator izlaza
            friend ostream& operator << (ostream& os, const IArray& a);
};
#endif
// Implementacija klase IArray
 
// Podrazumevani konstruktor
IArray::IArray (const int sz): size (sz) {
    // Rezervisanje celobrojnog niza sa size elemenata
    data = new int [ size ];
    // Inicijalizacija niza na 0
    for (int i = 0; i < size; i++)
        data[i] = 0;
}
 
// Alternativni konstruktor
IArray::IArray (const int *a, int sz) {
    Init (a, sz);
}
 
// Kopija konstruktora
IArray::IArray (const IArray& a) {
    Init (a.data, a.size);
}
 
// Destruktor
IArray::~IArray() {
    delete [] data;
    size=0;
    data=null;
}
 
// Inicijalizacija niza
void 
IArray::Init (const int* a, int sz) {
    size = sz;
    data = new int [size];
    for (int i = 0; i < size; i++)
        data[i] = a[i];
}
 
// Operator dodeljivanja
IArray& 
IArray::operator= (const IArray& a) {
    // Nema dodeljivanja samog sebi
    if (this != &a) {
        // Brisanje starog podatka
        delete [] data;
        // Rezervisanje novog podatka
        Init (a.data, a.size);
    }
return *this;
}
 
// Operator indeksiranja
int&
IArray::operator[] (int index) {
    return data[index];
}
 
// Velicina
int
IArray::Size () const {
return size;
}
 
// Operator izlaza
ostream&
operator<< (ostream& os, const IArray& a) {
    for (int i=0; i < a.size; i++) {
        os << "[";
        os.width(2); os << i;
        os << "]: ";
        os.width(3); 
        os << a.data[i];
        os << endl;
    }
return os;
}
// Test program main za klasu IArray
int main() {
    // Koristi podrazumevani konstruktor
    IArray a1;
    // Koristi drugi konstruktor da inicijalizuje
    // niz od int
    const int d[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
    IArray a2 (d, 12);
    // Kreira novi niz pomoću a2
    // da testira kopiju konstruktora
    IArray a3 (a2);
    // Koristi operator indeksa da
    // promeni a2
    for (int i = 0; i < a2.Size(); i++)
        a2[i] *= 10;
    // a2 se dodeljuje a1
    a1 = a2;
    // Stampa nizove
    cout << "A1 is " << endl << a1 << endl;
    cout << "A2 is " << endl << a2 << endl;
    cout << "A3 is " << endl << a3 << endl;
return 0;
}
Izlaz programa main
A1 is
[ 0]: 0
[ 1]: 10
[ 2]: 20
[ 3]: 30
[ 4]: 40
[ 5]: 50
[ 6]: 60
[ 7]: 70
[ 8]: 80
[ 9]: 90
[10]: 100
[11]: 110
A2 is
[ 0]: 0
[ 1]: 10
[ 2]: 20
[ 3]: 30
[ 4]: 40
[ 5]: 50
[ 6]: 60
[ 7]: 70
[ 8]: 80
[ 9]: 90
[10]: 100
[11]: 110
A3 is
[ 0]: 0
[ 1]: 1
[ 2]: 2
[ 3]: 3
[ 4]: 4
[ 5]: 5
[ 6]: 6
[ 7]: 7
[ 8]: 8
[ 9]: 9
[10]: 10
[11]: 11

Definicija klase ne rezerviše nikakvu memoriju. Memorija se rezerviše kada se objekat-niz kreira preko deklaracije promenljive. Konstruktori i destruktori obezbeđuju pravilnu inicijalizaciju i uništavanje objekta. Kada je objekat deklarisan, konstruktor se poziva da inicijalizuje memoriju koju koristi objekat.
Destruktor obavlja čišćenje (uništavanje) objekta kada objekat nije više potreban.
Posmatranjem implementacija klase IArray, vidimo da konstruktor rezerviše memoriju za podatak-niz, dok destruktor oslobađa tu memoriju.
Vodite računa da zaista nismo sakrili detalje implementacije od korisnika. C++ ne obezbeđuje način da se potpuno isključe svi detalji bazne implementacije, pošto privatni deo klase mora da bude obuhvaćen definicijom klase to je zgodno da se olabavi” pristup promenljivama unutar klase, konkretno preko nasleđivanja. Često izvedenim klasama treba lak pristup privatnim članovima njihovih roditeljskih klasa. C++ definiše službenu reč protected za tu svrhu.

Zaštićenim članovima može se pristupiti preko funkcija članica klase kao i funkcija članica izvedenih klasa. Međutim, kao što je slučaj sa privatnim članovima, zaštićenim članovima ne mogu pristupiti korisnikovi programi.Još jedna napomena o objektima. Upamtite da je prosleđivanje poruka fundamentalni način komunikacije između objekata. Kada napišete i < a2.Size(), vi u stvari šaljete poruku da objekat a2 niza
utvrdi veličinu niza i vrati tu vrednost. U stvarnosti, poruka se ne šalje. C++ emulira slanje poruka preko korišćenja funkcijskih poziva. Kompajler obezbeđuje da će korektna funkcija biti pozvana za željeni objekat. Prema tome, u C++ možete smatrati prosleđivanje poruke funkcijskim pozivom (pozivanjem funkcije).
Autor Dragan Marković & rand0m;

Unless otherwise stated, the content of this page is licensed under GNU Free Documentation License.