Delegarea (delegation) sau
Cand sa nu folosim mostenirea
Definitie
Delegarea reprezinta o modalitate de a extinde si reutiliza functiunile unei clase C1 prin crearea unei clase C2 cu functiuni noi si care utilizeaza instante ale clasei C1 pentru a indeplini functiunile originale.
Context
Extinderea si reutilizarea functiunilor unei clase se
obisnuieste sa se realizeze adesea prin mostenire. Mostenirea este utila
pentru a modela relatii de genul "este-un-fel-de" ("is-a-kind-of"). Aceste
relatii sunt statice in raport cu timpul. De aceea, nu in toate situatiile
este adecvata aplicarea mostenirii.
Delegarea este o modalitate mai generala pentru extinderea
comportamentului unei clase, care implica apelul metodelor clasei respective
in loc de mostenirea lor. Delegarea se preteaza la modelarea relatiilor
de tip "este-un-rol-jucat-de" ("is-a-role-played-by").
Exemplu: in cadrul unui sistem de evidenta a personalului
unei universitati avem de a face cu roluri ca: student, cadru didactic,
personal TESA. O posibilitate de a reprezenta acest ansamblu ar fi sa se
creeze o ierarhie de forma:
class Colectie {
Secventa *seq; public: void adauga(Obiect *unObiect) { seq -> add(unObiect); } //. . . }; |
Aici clasa Secventa poate fi o clasa de uz general care implementeaza o structura gen vector, lista etc. Ideea este ca, in loc sa derivam clasa Colectie din Secventa, aplicam delegarea (v. paragraful "Motivatii").
Motivatii
In practica proiectarii software
se intalnesc adesea utilizari inadecvate ale mostenirii, care au fost categorisite
ca "anti-sabloane". Printre acestea cele mai frecvente sunt:
Solutie
Delegarea reprezinta un mod de a reutiliza si extinde comportamentul unei clase. Ea se realizeaza scriind o noua clasa (delegatorul) care incorporeaza functionalitatea clasei originale (delegatul) prin intermediul unei instante a acesteia din urma:
Consecinte
Principalul dezavantaj al delegarii este gradul mai scazut de structurare fata de mostenire. Relatiile dintre clase modelate cu ajutorul delegarii sunt mai putin clare. In acest sens exista cateva cai de ameliorare a lucrurilor:
Implementare
Presupune obtinerea de catre clasa delegator a unei referinte
spre o instanta a clasei delegat si apelarea metodelor acesteia:
class Delegator {
Delegat *p; //. . . public: void metodaDelegator { //. . . p->metodaDelegat(); //. . . } }; |
Obs: initializarea
membrului p se poate face prin constructorul clasei Delegator
si/sau prin alte functii membru ale acesteia.
Tema
Se cere sa se defineasca o clasa Depozit care sa modeleze functionarea unui depozit comercial de marfuri (intrari de marfa, vanzari, afisarea unui inventar). Clasa va fi constituita ca o colectie de obiecte caracterizate prin nume, cod unic (care identifica in mod univoc diferitele produse), pret si cantitate. Comportamentul clasei Depozit se va obtine aplicand delegarea asupra unei clase "de uz general", gen Vector sau Lista, folosind operatiile specifice de adaugare/eliminare de elemente, respectiv parcurgere. Clasa delegat va fi definita tot in cadrul temei sau va fi preluata, daca e posibil, din biblioteca atasata mediului de programare folosit.