Sunteți pe pagina 1din 169

S ABLOANE DE PROIECTARE

IOLU Mihai-S tefan 4 martie 2014

ii

Cuprins
1 Prezentare general a 1.1 Ce este un sablon de proiectare? 1.2 De ce sunt utile? . . . . . . . . . 1.3 Clasicarea sabloanelor . . . . . 1.3.1 Smart Pointers n C++ . 1.3.2 Un sablon HTML si CSS 1 1 3 4 4 7

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

S abloane creat ionale

11
13 17 23 29 35

2 Singleton 3 Factory Method 4 Abstract Factory 5 Builder 6 Prototype

II

S abloane structurale

39
41 47

7 Adapter 8 Bridge

9 Fa cade 51 9.1 Scop si motivare . . . . . . . . . . . . . . . . . . . . . . . . 51 iii

iv 9.2 9.3 9.4 9.5 Alte solut ii mai Aplicare . . . . Structur a . . . Exemplu . . . . bune? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CUPRINS . . . . . . . . . . . . . . . . 51 52 53 54 55 55 56 56 57 58 61 61 63 63 63 64 67 67 68 69 69 75 75 76 76 76 79

10 Composite 10.1 Scop si motivare . . . 10.2 Alte solut ii mai bune? 10.3 Aplicare . . . . . . . . 10.4 Structur a . . . . . . . 10.5 Exemplu . . . . . . . . 11 Decorator 11.1 Scop si motivare . . . 11.2 Alte solut ii mai bune? 11.3 Aplicare . . . . . . . . 11.4 Structur a . . . . . . . 11.5 Exemplu . . . . . . . . 12 Flyweight 12.1 Scop si motivare 12.2 Aplicare . . . . . 12.3 Structur a . . . . 12.4 Exemplu . . . . . 13 Proxy 13.1 Scop si motivare 13.2 Aplicare . . . . . 13.3 Structur a . . . . 13.4 Exemplul 1 . . . 13.5 Exemplul 2 . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

III

S abloane comportamentale

83
85 85 86 86

14 Chain of Responsability 14.1 Scop si motivare . . . . . . . . . . . . . . . . . . . . . . . . 14.2 Aplicare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.3 Structur a . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CUPRINS 15 Command 15.1 Scop si motivare 15.2 Aplicare . . . . . 15.3 Structur a . . . . 15.4 Exemplu . . . . . 16 Interpreter 16.1 Scop si motivare 16.2 Aplicare . . . . . 16.3 Structur a . . . . 16.4 Exemplu . . . . . 17 Iterator 17.1 Scop si motivare 17.2 Aplicare . . . . . 17.3 Structur a . . . . 17.4 Exemplu . . . . . 18 State 18.1 Scop si motivare 18.2 Aplicare . . . . . 18.3 Structur a . . . . 18.4 Exemplu . . . . . 19 Strategy 19.1 Scop si motivare 19.2 Aplicare . . . . . 19.3 Structur a . . . . 19.4 Exemplul 1 . . . 19.5 Exemplul 2 . . . 19.6 Exemplul al 3-lea

v 89 89 90 91 92 97 97 99 99 101

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

105 . 105 . 106 . 106 . 107 111 . 111 . 111 . 112 . 113 117 . 117 . 118 . 119 . 120 . 121 . 122 125 . 125 . 126 . 127 . 128 . 128

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

20 Observer 20.1 Scop si motivare . 20.2 Aplicare . . . . . . 20.3 Structur a . . . . . 20.4 Exemple . . . . . . 20.4.1 Exemplul 1

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

vi

CUPRINS 20.4.2 Exemplul 2 . . . . . . . . . . . . . . . . . . . . . . . 129 20.4.3 Exemplul 3 . . . . . . . . . . . . . . . . . . . . . . . 131

21 Mediator 21.1 Scop si motivare 21.2 Aplicare . . . . . 21.3 Structur a . . . . 21.4 Exemplu . . . . . 22 Memento 22.1 Scop si motivare 22.2 Aplicare . . . . . 22.3 Structur a . . . . 22.4 Exemplu . . . . . 23 Visitor 23.1 Scop si motivare 23.2 Aplicare . . . . . 23.3 Structur a . . . . 23.4 Exemplu . . . . . 24 Template 24.1 Scop si motivare 24.2 Aplicare . . . . . 24.3 Structur a . . . . 24.4 Exemplu . . . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

135 . 135 . 136 . 137 . 138 143 143 143 144 145 149 149 150 150 151

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

155 . 155 . 156 . 156 . 158

25 Concluzii 161 25.1 Ce s a a stept am de la sabloanele de design? . . . . . . . . . 161 25.1.1 Un vocabular comun de design . . . . . . . . . . . . 161 25.1.2 Un ajutor pentru nv a tare si documentare . . . . . . 162

Capitolul 1

Prezentare general a
Scopul sabloanelor de design este de a nregistra experient a referitoare la programarea obiect-orientat a. Fiecare astfel de sablon nume ste, explic a si evalueaz a un design n sisteme obiect orientate.

1.1

Ce este un sablon de proiectare?

Prima oar a, n literatura de specialitate conceptul de sablon (pattern) a ap arut n anul 1977 c and Christopher Alexander a publicat cartea A Pattern Language. In cartea sa el nu a scris despre sabloane de proiectare n domeniul informaticii, ci despre moduri de a automatiza procesul de realizare a unei arhitecturi de succes. El d a si prima denit ie a ceea ce ar putea nsemna un sablon de proiectare: Fiecare sablon descrie o problem a care tot apare n mediul nostru, dup a care descrie esent a solut iei acelei probleme, n a sa fel nc at ea s a poat a folosit a de mii de ori, f ar a a mai face acela si lucru de mai multe ori. Aceast a carte a lui care a promovat ideea de sablon n arhitectur a i-a f acut pe cei care se ocupau de industria software s a se ntrebe dac a acela si lucru nu ar putea valabil si pentru domeniul informaticii. Intrebarea care se punea era urm atoarea: dac a se poate arma c a un design este bun, cum se poate face ca prin anumit i pa si s a putem automatiza obt inerea unui astfel de design? Tot Christopher Alexander este cel care a adus n prim plan ideea c a, n general, n viat a de zi cu zi, aceste sabloane se compun unele cu altele 1

CAPITOLUL 1. PREZENTARE GENERALA

conduc and la solut ii mai complexe care agreg a mai multe sabloane. Momentul care a condus la popularizarea pe scar a larg a a not iunii de sablon de proiectare n domeniul informaticii a fost aparit ia n 1995 a c art ii Design patterns - Elements of Reusable Object Oriented Software, carte scris a de E. Gamma, R. Helm, Johnsson si Vlissides. In aceast a carte cei patru autori nu au meritul de a inventat sabloanele de proiectare pe care le-au prezentat ci mai degrab a ei au documentat ceea ce deja exista n sistemele soft ale vremii respective. Principalele lor merite sunt urm atoarele: au introdus ideea de sablon n industria software au catalogat si descris ecare sablon n parte au prezentat ntr-un mod logic, strategiile care stau la baza acestor sabloane de proiectare. Aceast a carte este una din cele mai de succes c art i de informatic a din toate timpurile. Chiar si la aproximativ 20 ani de la aparit ia ei, ea este citat a si utilizat a la fel de mult ca la nceput, dac a nu chiar si mai mult. In semn de apreciere, autorii acesteia sunt cunoscut i sub numele de Gang of Four (GoF). Nu numai cei patru care au scris aceast a carte au un merit deosebit la popularizarea sabloanelor de proiectare. Exist a si alte persoane, care sunt poate chiar mai importante datorit a faptului c a ele au introdus aceste concepte. Nume precum Kent Beck, Ward Cunningham si James Coplien au contat foarte mult n dezvoltarea acestui domeniu. O alt a denit ie a unui sablon de design, care este dat a chiar de c atre cei patru sun a astfel: S abloanele de proiectare sunt descrieri ale unor obiecte si clase care comunic a si care sunt particularizate pentru a rezolva o problem a general a de design ntr-un context particular. In continuare prezent am o ultim a denit ie care i apart ine tot lui Christopher Alexander. Chiar dac a ea a fost g andit a referitor la arhitectur a ea este foarte potrivit a n domeniul informaticii: Fiecare sablon de proiectare este o regul a n trei p art i, care exprim a o relat ie ntre un context, o problem a si o solut ie. Dup a cum vom vedea n continuare, pentru a descrie un sablon de proiectare, trebuie neap arat s a specic am urm atoarele lucruri:

1.2. DE CE SUNT UTILE?

numele sablonului - este important deoarece el ne ajut a s a comunic am mai u sor cu cei cu care lucr am problema - descrierea situat iei n care se aplic a solut ia - modalitatea de a rezolva acea problem a consecint ele - avantajele si dezavantajele acelei abord ari

1.2

De ce sunt utile?

P an a acum am v azut ce sunt sabloanele de proiectare. O alt a ntrebare legitim a n acest moment ar , de ce sunt ele utile. Oare este neap arat necesar s a nt elegem conceptul de sablon de proiectare? Este neap arat necesar s a cunoa stem exemple de sabloane de proiectare? R aspunsul autorului este c a da, din mai multe motive: Utilizarea sabloanelor de proiectare conduce la reutilizarea unor solut ii care si-au ar atat de-a lungul timpului ecient a. Dup a cum se stie una din cele mai importante probleme n domeniul informaticii tine de reutilizabilitate. Dac a p an a acum am tot vorbit despre reutilizarea codului, oare nu se poate ca reutilizarea ideilor s a e la fel de important a? Permit stabilirea unei terminologii comune. Practic, printr-un singur cuv ant se poate ca s a comunic am ceea ce altfel ar destul de greu de prezentat. Ofer a o perspectiv a mai nalt a asupra analizei si designului sistemelor obiect orientate. Au ca principal obiectiv crearea de cod exibil, u sor de modicat. Scopul lor este ca, n m asura n care este posibil, s a permit a ad augarea de noi funct ionalit a ti f ar a a modica cod existent. Odat a nt elese bine, ele sunt ni ste exemple foarte bune relativ la principiile de baz a ale program arii obiect orientate. Permit nsu sirea unor strategii mbun at a tite care ne pot ajuta si atunci c and nu lucr am cu sabloanele de proiectare:

CAPITOLUL 1. PREZENTARE GENERALA Lucrul pe interfet e nu pe implement ari Favorizarea compozit iei n dauna mo stenirii G asirea elementelor care variaz a si ncapsularea lor

1.3

Clasicarea sabloanelor

In funct ie de nivelul la care apar, sabloanele sunt de mai multe feluri: idioms - sunt primele care au ap arut si sunt dependente de anumite tehnologii (de exemplu, lucrul cu smart pointers n limbajul C++). design patterns - reprezint a solut ii independente de un anumit limbaj, putem spune c a sunt un fel de microarhitecturi (ele sunt cele care vor prezentate n continuare). framework patterns - sunt sabloane la nivel de sistem, adic a sunt sabloane care sunt folosite pentru a descrie la nivel nalt arhitectura unui ntreg sistem. Exist a sabloane care de-a lungul timpului au evoluat, de la prima categorie c atre ultima: MVC (Model View Controller). Din punctul de vedere al scopului lor, sabloanele de proiectare se mpart n 3 categorii: creat ionale - abstractizeaza procesul de creare a obiectelor pentru a cre ste exibilitatea designului structurale - permit gruparea obiectelor n structuri complexe comportamentale - permit denirea unui cadru optim pentru realizarea comunic arii ntre obiecte. In cele ce urmeaz a vom prezenta, pe scurt, un idiom, pentru a putea face ulterior o comparat ie ntre el si sabloanele de proiectare.

1.3.1

Smart Pointers n C++

Dup a cum vom vedea, smart pointers sunt ni ste obiecte care simuleaz a ni ste pointeri adev arat i, prin implementarea operatorului > si a operatorului unar *.

1.3. CLASIFICAREA S ABLOANELOR

In plus, pointerii inteligent i rezolv a probleme precum managementul memoriei, respectiv blocarea unui anumit obiect. Un smart pointer este un obiect care simuleaz a un pointer, dar care poate face mai multe lucruri. Un astfel de smart pointer ar putea implementat ntr-o clasa SmartPtr astfel: template<class T> class SmartPtr { public: explicit SmartPtr(T* pointee) : pointee_(pointee); SmartPtr& operator=(const SmartPtr& other); ~SmartPtr(); T& operator*() const { ... return *pointee_; } T* operator->() const { ... return pointee_; } private: T* pointee_; ... }; Aceast a clas a poate folosit a ntr-un cod de genul urm ator: class Widget { public: void Fun(); }; SmartPtr<Widget> sp(new Widget);

6 sp->Fun(); (*sp).Fun();

CAPITOLUL 1. PREZENTARE GENERALA

O funct ionalitate a acestui smart pointer ar putea , ca n destructor s a se elibereze memoria pentru pointerul pe care-l ret ine. In aceast a situat ie nu ar mai necesar s a eliber am memoria prin folosirea operatorului delete, ci se va putea benecia de faptul c a smart pointerul este un obiect alocat, de cele mai multe ori pe stiv a, astfel nc at pentru el se elibereaz a automat memoria. In C++, se poate folosi conceptul de smart pointer cu ajutorul clasei auto ptr. Un exemplu de folosire simplu, n care ignor am intent ionat mai multe lucruri referitoare la declararea clasei Stack, ar putea ar ata astfel: #include<iostream> #include<memory> using namespace std; template <class T> class Stack { T* a; int count; public: Stack(int dim) { count=0; a=new T[dim]; } void Push(T x) { a[count++]=x; } T Pop() { return a[--count]; } T Top()

1.3. CLASIFICAREA S ABLOANELOR { return a[count-1]; } int IsEmpty() { return count==0; } ~Stack() { cout<<"in destructor..."<<endl; delete [] a; } }; void main() { auto_ptr<Stack<int>> p(new Stack<int>(20)); p->Push(3); p->Push(6); cout<<p->Top()<<endl; }

Clasa auto ptr are ca efect, eliberarea automat a a memoriei pentru obiectul pentru care e folosit a. Pentru a putea folosi aceast a clas a trebuie inclus sierul header memory.h.

1.3.2

Un sablon HTML si CSS

Ideea de sablon de proiectare a prins at at de bine nc at mai nou au ap arut sabloane de design n numeroase domenii. In cartea Pro CSS and HTML Design Patterns sunt prezentate numeroase solut ii la probleme din domeniul designului web. De exemplu, cum am putea s a construim o structur a de genul celei prezentate n gura 1.1, f ar a a folosi tabele? In cartea despre care am vorbit, se contruiesc un sier HTML si un sier CSS. Fi sierul HTML va ar ata astfel:

CAPITOLUL 1. PREZENTARE GENERALA

Figura 1.1: Aplicarea Fluid Layout Overview <html> <head> <LINK REL=StyleSheet HREF="style.css" TYPE="text/css"> </head> <body> <h1>Fluid Layout Overview</h1> <div id="nav"> <h2>Navigation</h2> <p>20% of containers width.</p></div> <div id="main"> <h2>Main</h2> <p>40% of containers width.</p></div> <div id="news"> <h2>News</h2> <p>20% of containers width.</p></div> </body> <html> Fi sierul styles.css va cont ine urm atoarele: body { max-width:1000px; margin-left:auto; margin-right:auto; } div { background-color:gold; margin-right:10px; padding:5px;

1.3. CLASIFICAREA S ABLOANELOR

border-left:1px solid gray; border-right:2px solid black; border-top:1px solid gray; border-bottom:2px solid black; } #nav { float:left; width:20%; min-width:170px; } #main { float:left; width:40%; min-width:170px; } #news { float:left; width:20%; min-width:170px; } /* Nonessential rules are not shown. */ Acest sablon poart a numele de Fluid Layout Overview. El rezolv a problema a s arii pe coloane a mai multor informat ii n situat ii n care nu se dore ste folosirea tabelelor, deoarece acestea nu sunt potrivite. Dorim ca, n situat ia n care nu se pot a sa toate coloanele, ele s a e automat transformate n r anduri si s a ram an a accesibile. Acest lucru se poate nt ampla mai ales atunci c and avem un dispozitiv mobil. Vrem deasemenea ca s a avem coloane care s a se extind a, dar numai p an a la o anumit a dimensiune, deoarece coloanele prea largi conduc la un text mai greu de citit. Pe de alt a parte, vrem ca s a nu e posibil ca o coloan a s a e mic sorat a foarte mult, astfel nc at textul ei s a nu mai poat a citit. Toate aceste lucruri sunt rezolvate de sablonul precedent, cu ajutorul elementelor < div > din HTML si a CSS-ului.

10

CAPITOLUL 1. PREZENTARE GENERALA

Partea I

S abloane creat ionale

11

Capitolul 2

Singleton
Scop
Asigur a faptul c a o clas a are o singur a instant a si ofer a un singur punct de acces global la ea.

Motivare
In anumite situat ii vrem ca o clas a s a aib a o singur a instant a care s a poat a accesat a de oriunde dintr-o aplicat ie. Am putea folosi n acest caz o variabil a global a, dar atunci am putea crea oric ate instant e ale acelei clase. Am putea de exemplu s a avem n obiect un c amp static care s a numere c ate obiecte au fost create si s a genereze eroare c and vrem s a creem unul nou, dar acest lucru nu este at at de elegant, precum solut ia pe care o vom prezenta n continuare si nici nu rezolv a problema accesului global la acea instant a.

Aplicabilitate
Aplic am acest sablon de proiectare atunci c and: Vrem s a existe o singur a instant a a unei clase, care s a poat a accesibil a client ilor printr-un punct de acces binecunoscut. 13

14

CAPITOLUL 2. SINGLETON C and singura instant a trebuie s a poat a extensibil a prin subclasare si client ii ar trebui s a e capabili s a foloseasc a o instant a extins a f ar a a- si modica codul.

Structur a
Structura sablonului de proiectare Singleton este prezentat a n gura 2.1.

Figura 2.1: Structura sablonului Singleton Dup a cum se poate observa, pentru a rezolva aceast a problem a trebuie s a facem nt ai si nt ai astfel nc at s a nu putem crea obiecte de tipul Singleton. Acest lucru se face prin realizarea unui constructor privat. Un obiect de tip Singleton este ret inut ntr-o instant a static a de tip Singleton. Foarte important este rolul metodei statice getInstance() care arat a astfel: public static Singleton getInstance() { if(instance==null) instance=new Singleton(); return instance; } Astfel, dac a atunci c and este cerut obiectul acesta exist a, atunci el este doar returnat f ar a a se creea altul. Dac a el nu exist a, atunci este creat si apoi returnat. Singura modalitate prin care se poate accesa obiectul unic de tip Singleton este prin intermediul metodei getInstance().

15 Folosirea acestui sablon are mai multe consecint e: Prin faptul c a nu se folose ste o variabil a global a, se asigur a nepoluarea spat iului de nume cu o nou a denumire. Permite subclasarea unei clase de tip Singleton, astfel nc at noua clas a s a poat a avea ea ns a si o singur a existent a. Cu anumite modic ari se poate obt ine o nou a clas a care poate crea un num ar limitat de obiecte, dar mai mult dec at unul.

Exemplu
In cele ce urmeaz a este prezentat un exemplu care ilustreaz a modul n care se poate folosi acest sablon de proiectare. Am construit n continuare o clas a Printer care simuleaz a o imprimant a. Pentru aceast a clas a trebuie s a avem o singur a instant a la un moment dat, lucru care este asigurat de folosirea sablonului de proiectare Singleton. public class Printer { private static Printer instance; private Printer() { } public synchronized static Printer getPrinter() { if(instance==null) instance=new Printer(); return instance; } public synchronized void print(String str) { System.out.println("Text de tiparit: "+str); try { Thread.sleep(2000);

16

CAPITOLUL 2. SINGLETON } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Terminat de tiparit..."); }

} class TiparireThread extends Thread { private String textDeTiparit; public TiparireThread(String str) { textDeTiparit=str; } public void run() { Printer p=Printer.getPrinter(); p.print(textDeTiparit); } } public class TestSingleton { public static void main(String[] args) { TiparireThread t1=new TiparireThread("primul text..."); TiparireThread t2=new TiparireThread("al doilea text..."); t1.start(); t2.start(); } }

Capitolul 3

Factory Method
Inc arcarea dinamic a a claselor
Inc arcarea dinamic a a claselor este mecanismul prin care n limbajul Java se poate nc arca si folosi n timpul rul arii programului, o clas a care nu exist a neap arat la momentul compil arii. Acest lucru se nt ampl a, de exemplu, n momentul n care lucr am cu baze de date atunci c and scriem cod precum: Class.forName("com.mysql.jdbc.Driver"); In plus, n momentul n care se ncarc a dinamic o clas a se execut a si init ializatorul ei static. Acesta este o construct ie de tipul urm ator, care poate init ializa atribute statice si eventual efectueaz a anumite operat ii n plus: class Test { static { ... codul pentru initializator } ... } In cele ce urmeaz a vom prezenta codul pentru o aplicat ie care folose ste nc arcarea dinamic a a claselor si init ializatorul static. 17

18

CAPITOLUL 3. FACTORY METHOD

public interface Interfata { void metoda(); }

public class TestDinamic { public static void main(String[] args) throws InstantiationExcepti IllegalAccessException, ClassNotFoundException { Interfata i; System.out.println("incepe programul..."); i=(Interfata)Class.forName("Clasa").newInstance(); i.metoda(); } } public class Clasa implements Interfata{ static { System.out.println("in initializatorul static..."); } public void metoda(){ System.out.println("s-a apelat metoda..."); } }

Scop
Dene ste o interfat a pentru crearea unui obiect, dar las a subclasele s a decid a care clas a trebuie instant iat a. Permite unei clase s a transfere responsabilitatea instant ierii c atre subclase.

Motivare
In aceast a sect iune vom prezenta ceea ce se nt ampl a ntr-un framework n care dorim s a creem mai multe tipuri de documente diferite. Totu si, pentru aceste tipuri de documente, chiar dac a ele sunt diferite, exist a anumite lucruri care se petrec la fel.

19 In acest caz trebuie s a separ am lucrurile care sunt comune de cele care variaz a, lucru ilustrat n gura 3.1

Figura 3.1: Motivare Factory Method In aceast a diagram a partea comun a este reprezentat a de interfat a Document (partea comun a tuturor documentelor) si de clasa abstract a Application (partea comun a tuturor aplicat iilor).

Aplicabilitate
Se folose ste Factory Method atunci c and: O clas a nu poate anticipa clasele obiectelor pe care va trebui s a le creeze. O clas a vrea ca subclasele sale s a specice obiectele pe care le creeaz a.

Structur a
Structura acestui sablon este prezentat a n diagrama 3.2. Se poate observa n gura 3.2 c a avem o clas a abstract a Creator n care avem denit a o metod a abstract a care are rolul de a crea si returna un anumit tip de obiect de tipul Product. Aceast a metod a este rescris a ntr-o subclas a pentru a realiza o anumit a operat ie. Trebuie precizat faptul c a acest sablon are mai multe consecint e:

20

CAPITOLUL 3. FACTORY METHOD

Figura 3.2: Structura sablonului Factory Permite crearea unui framework generic n care ulterior se poate ad auga funct ionalitate, prin suprascrierea unor anumite metode si folosirea polimorsmului. Este o ilustrare a principiului: C and ceva variaz a acel lucru trebuie ncapsulat. In cazul nostru s-a ncapsulat funct ionalitatea comun a n clasa Creator. Crearea unui obiect printr-o metod a factory este mai bun a pe termen lung deoarece astfel se poate foarte u sor aplica aceea si logic a prin crearea unei noi clase si suprascrierea unei singure metode. Exist a, n practic a si metode factory care primesc un parametru care specic a tipul obiectului care va creat.

Exemplu
Am ales ca exemplu pentru acest capitol o aplicat ie care implementeaz a un pic diferit sablonul Factory Method, dar care ne va ajuta s a nt elegem mai bine sablonul de proiectare din capitolul urm ator. In primul r and denim o interfat a Shape: public interface Shape { void draw(); } Dup a aceasta denim o clas a ShapeFactory care stie s a creeze obiecte de tip Shape pe baza unui sir de caractere transmis ca parametru.

21 import java.util.*; public abstract class ShapeFactory { protected abstract Shape create(); private static Map<String, ShapeFactory> factories= new HashMap<String, ShapeFactory>(); public static void addFactory(String id, ShapeFactory f) { factories.put(id, f); } public static final Shape createShape(String id) { if(!factories.containsKey(id)) { try { Class.forName(id); } catch (ClassNotFoundException e) { e.printStackTrace(); } if(!factories.containsKey(id)) throw new RuntimeException("This id does not exist..."); } return ((ShapeFactory)factories.get(id)).create(); } } Avem dou a clase Circle si Square care se nregistreaz a singure n fabrica de obiecte prezentat a anterior: public class Circle implements Shape{ private Circle(){}; public void draw() { System.out.println("Circle.draw()..."); } private static class Factory extends ShapeFactory { protected Shape create() { return new Circle();

22 } }

CAPITOLUL 3. FACTORY METHOD

static { ShapeFactory.addFactory("Circle", new Factory()); } } public class Square implements Shape{ private Square(){}; public void draw() { System.out.println("Square.draw()..."); } private static class Factory extends ShapeFactory { protected Shape create() { return new Square(); } } static { ShapeFactory.addFactory("Square", new Factory()); } } In cele din urm a prezent am o mic a aplicat ie care ilustreaz a modul n care se pot folosi clasele prezentate anterior: import java.util.*; public class TestPolymorphicFactories { public static void main(String[] args) { String[] list={"Circle","Square","Circle"}; List<Shape> shapes=new ArrayList<Shape>(); for(String shapeName:list) shapes.add(ShapeFactory.createShape(shapeName)); for(Shape shape:shapes) shape.draw(); } }

Capitolul 4

Abstract Factory
Scop
Ofer a o interfat a pentru crearea familiilor de obiecte nrudite sau dependente f ar a a specica clasele lor concrete.

Motivare
Un astfel de sablon de proiectare se folose ste n JAVA pentru a construi cadrul pentru lucrul cu baze de date n JDBC. Iat a, n gura 4.1 modul n care sunt denite principalele clase si interfet e folosite pentru lucrul cu baze de date n Java. Dup a cum se poate u sor observa, pentru a lucra cu baze de date se folosesc n codul pe care-l scriem mai mult interfet e dec at clase propriuzise. Avem astfel un exemplu care ilustreaz a lucrul pe interfet e nu pe implement ari. Acest lucru este necesar deoarece, cei care au f acut limbajul Java nu au putut scrie codul pentru ecare tip de sistem de gestiune al bazelor de date care ar putea folosit mpreun a cu limbajul Java, ci mai degrab a au l asat acest lucru pe seama implementatorilor SGBD-urilor. Astfel, noi c and lucr am cu baze de date n Java, de fapt lucr am pe ni ste interfet e, codul propriu zis care este apelat, pentru a realiza conexiuni cu serverul de baze de date si pentru a efectua diverse operat ii ind cuprins in driver-ul pe care l folosim. 23

24

CAPITOLUL 4. ABSTRACT FACTORY

Figura 4.1: Arhitectura JDBC Reamintim c a un driver este un sier JAR care trebuie inclus la momentul rul arii aplicat iei. El este responsabil cu tot ceea ce tine de comunicarea cu serverul de baze de date. Aceast a arhitectur a prezint a mai multe avantaje, precum faptul c a n acest fel num arul de SGBD-uri suportate de Java este practic nelimitat. Oricine vrea s a- si construiasc a un SGBD, poate face acest lucru si, mai mult, dup a ce- si construie ste propriul driver, poate accesa acest SGBD din Java. In continuare este prezentat a o mostr a de cod care acceseaz a o baz a de date n limbajul Java: Class.forName("com.mysql.jdbc.Driver"); conn=DriverManager.getConnection( "jdbc:mysql://localhost:3306/bazamea","root",""); Statement s=conn.createStatement(); ResultSet rs=s.executeQuery("select * from persoane");

25 while(rs.next()) { long id=rs.getLong("persoana_id"); String nume=rs.getString("nume"); String prenume=rs.getString("prenume"); String oras=rs.getString("oras"); Date d=rs.getDate("data_nasterii"); SimpleDateFormat sdf=new SimpleDateFormat("dd/MM/yyyy"); System.out.println(String.format("%-20s %10s %12s", nume+ " "+prenume, oras, sdf.format(d))); } conn.close(); Vom prezenta n sect iunea dedicat a exemplelor ce se nt ampl a de fapt n acest cod.

Aplicabilitate
Se folose ste Abstract Factory atunci c and: Un sistem trebuie s a e independent de modul n care produsele sale sunt create, compuse si reprezentate. Un sistem trebuie s a poat a i congurat cu una din mai multe familii de produse. Mai multe produse de acela si tip trebuie folosite mpreun a si vrem s a fort am aceast a constr angere. Vrem s a oferim o libr arie de clase, si vrem s a lucr am doar pe interfet ele lor nu si pe implement ari.

Structur a
Structura acestui sablon este prezentat a n gura 4.2 Dup a cum se poate vedea avem o interfat a AbstractFactory care descrie modul n care se pot crea obiectele. Aceast a interfat a este implementat a de c ate o clas a pentru ecare tip de familie de obiecte n parte.

26

CAPITOLUL 4. ABSTRACT FACTORY

Figura 4.2: Structura sablonului Abstract Factory De asemenea, pentru ecare tip de obiect n parte exist a c ate o interfat a care descrie funct ionalitatea lui. Folosirea acestui sablon are mai multe consecint e: Prin folosirea fabricii de obiecte se izoleaz a client ii de produsele efective pe care le folosesc. Acest lucru reprezint a o modalitate de asigurare a ncapsul arii. Folosirea Abstract Factory ajut a la schimbarea u soar a a familiilor de obiecte. Pentru a realiza acest lucru trebuie schimbat a o singur a linie de cod. Se promoveaz a consistent a ntre diversele familii de produse. Un posibil dezavantaj al acestei abord ari este faptul c a este mai greu de ad augat un nou tip de produs. Acest lucru ar presupune modicarea mai multor clase (toate cele din lant ul de derivare al lui AbstractFactory) precum si introducerea mai multor clase corespunz atoare noului produs.

27

Exemplu
In sect iunea referitoare la acest sablon de proiectare vom prezenta modul n care ar trebui folosit a o familie de produse precum si modul n care se poate modica familia de produse folosit a. AbstractFactory factory=new ConcreteFactory1(); //AbstractFactory factory=new ConcreteFactory2(); AbstractProductA pa=factory.createProductA(); AbstractProductB pb=factory.createProductB(); A doua parte a acestei sect iuni va prezenta ce se nt ampl a n spatele cortinei atunci c and vrem s a ne conect am la o baz a de date n Java: 1. Se ncarc a dinamic clasa din pachetul JAR corespunz atoare driverului cu care vrem s a lucr am. 2. Aceast a clas a are un init ializator static care este executat. In acest init ializator este asociat un obiect de tip Driver corespunz ator driverului utilizat (com.mysql.jdbc.Driver dac a lucr am cu baze de date MySQL) unui sir de caractere care descrie acel driver (de ex jcdb:mysql://). 3. C and se apeleaz a metoda getConnection() a clasei DriverManager, de fapt se parcurge lista de drivere, se selecteaz a cel corespunz ator sirului de caractere transmis si cu ajutorul acestuia se creeaz a o nou a conexiune, care este returnat a (un fel ce com.mysql.jdbc.Connection). Aceast a conexiune reprezint a fabrica concret a de obiecte. 4. Cu ajutorul acestei fabrici de obiecte se creeaz a mai multe obiecte de tipul Statement, PreparedStatement etc. Pentru a putea nt elege foarte bine corespondent ele ntre clasele existente n cazul lucrului cu baze de date si a sablonului de proiectare Abstract Factory, este bine s a vedem ce rol are ecare clas a: AbstractFactory - java.util.Connection ConcreteFactory - com.mysql.jdbc.Connection

28

CAPITOLUL 4. ABSTRACT FACTORY AbstractProduct - Stament, PreparedStatement, CallableStatement ConcreteProduct - com.mysql.jdbc.Statement, etc. Cel mai bine se vede acest lucru dac a urm arim gura 4.3.

Figura 4.3: Ilustrare Abstract Factory n JDBC

Capitolul 5

Builder
Scop
Separ a construct ia unui obiect complex de reprezentarea sa astfel nc at acela si proces de construct ie s a poat a crea reprezent ari diferite.

Motivare
In aceast a sect iune prezent am o situat ie n care am dori s a transform am un text, ret inut n format RTF (Rich Text Format) ntr-un alt format care poate de mai multe feluri. Solut ia acestei probleme trebuie s a tin a seama de faptul c a num arul de conversii pe care vrem s a le facem este open-ended (oric and pot ap area noi tipuri de conversii pe care vrem s a le suport am). Clasele care realizeaz a conversia poart a numele de builder iar clasa care ret ine o referint a la convertor si care controleaz a procesul de conversie poart a numele de director. Remarc am mai multe lucruri: Oric and am dori s a cre am un nou convertor, acest lucru s-ar putea face foarte u sor prin subclasarea clasei TextConverter. Clasa RTFReader nu este n nici un fel con stient a de tipurile de obiecte pe care le creeaz a. Oric and se pot crea convertoare care s a genereze noi tipuri de documente. 29

30

CAPITOLUL 5. BUILDER

Figura 5.1: Motivare pentru sablonul Builder Convertorul nu trebuie folosit neap arat cu un anumit Reader. El poate folosit si de c atre alte clase (conceptul ilustrat aici: c and ceva variaz a, acel lucru trebuie ncapsulat). Codul de folosire a unui astfel de builder ar putea ar ata ceva de genul: RTFReader reader=new RTFReader("docu.rtf"); ASCIIConverter conv=new ASCIIConverter(); reader.setConverter(conv); reader.parseRTF(); ASCIIText text=conv.getASCIIText(); Dup a cum se poate u sor observa se parcurg urm atorii pa si n momentul n care se lucreaz a cu acest sablon: Clientul creeaz a un obiect director si-l congureaz a cu un anumit builder. Directorul notic a builderul oric and el trebuie s a adauge ceva nou. Builderul prime ste cererile de la director si adaug a noi p art i ale obiectului nal.

31 Clientul obt ine obiectul nal direct de la builder. S-ar putea obt ine si direct de la director dar acest lucru ar nsemna c a trebuie s a avem o interfat a comun a a obiectelor care pot create.

Alte solut ii mai bune?


Pentru a nt elege si mai bine acest sablon ar bine s a ne g andim cum altfel am putea rezolva aceast a problem a. La prima vedere, probabil c a ne-am g andi s a deriv am c ate o clas a din RTFReader pentru ecare tip de conversie pe care vrem s a o facem. Aceast a abordare are c ateva probleme: Dac a am vrea s a putem folosi si un alt tip de reader atunci ar trebui s a facem mai multe clase reader, din care s a deriv am toate tipurile de clase necesare pentru a putea face toate tipurile de transform ari. Readerul nu ar mai putea congurat la momentul rul arii cu un anumit builder. Num arul de clase ar mai mare. Practic el ar egal cu m n unde m reprezint a num arul de readeri iar n reprezint a num arul de builderi.

Aplicabilitate
Se aplic a acest sablon de proiectare n situat ia n care: Algoritmul pentru crearea unui obiect complex ar trebui s a e independent de p art ile care alc atuiesc obiectul si modul n care sunt ele asamblate. Procesul de construct ie trebuie s a permit a diferite reprezent ari pentru obiectele care sunt construite.

Structur a
Privind la structura acestui sablon se pot trage mai multe concluzii: Izoleaz a codul pentru construct ie si reprezentare.

32

CAPITOLUL 5. BUILDER

Figura 5.2: Structura sablonului Builder Dup a cum se poate vedea obiectul care este creat, este obt inut pas cu pas, prin apeluri repetate ale metodelor builderului. El este returnat clientului numai la nal. Nu avem nici o clas a abstract a pentru produse deoarece putem avea produse at at de diferite nc at este foarte greu s a denim o interfat a comun a a lor. Acest lucru nu este o problem a pentru c a, oricum, clientul este con stient de builderul pe care-l folose ste si atunci este de presupus c a el stie si ce tip de produs este returnat. De multe ori metodele builderului nu sunt declarate abstracte ci mai degrab a sunt metode empty. S-a folosit principiul conform c aruia se favorizeaz a compozit ia n dauna mo stenirii. Acest lucru este prezentat n sect iunea n care am ncercat s a prezint o rezolvare alternativ a a acestei probleme. De asemenea, s-a folosit principiul conform c aruia c and ceva variaz a, acel lucru trebuie ncapsulat.

Exemplu
Prezent am n cele ce urmeaz a un mic exemplu care cite ste un sier text si transform a cont inutul lui astfel nc at s a poat a folosit ntr-un sier de propriet a ti sau ntr-un document XML.
public interface Builder { void addProperty(String property, String value);

33
} -------------------import java.io.*; public class Director { private String fileName; private Builder builder; public Director(String fileName){ this.fileName=fileName; } public void setBuilder(Builder builder){ this.builder=builder; } public void parseText() throws IOException{ int i=0; String str=null, aux=null; BufferedReader buf=new BufferedReader(new FileReader(fileName)); while((str=buf.readLine())!=null){ if(i%2==0) aux=str; else builder.addProperty(aux, str); i++; } if(i%2==1) throw new RuntimeException("Nu s-a reusit parsarea!!!"); buf.close(); } } -------------------public class PropertiesBuilder implements Builder{ private StringBuffer text; public PropertiesBuilder(){ text=new StringBuffer(""); } public void addProperty(String property, String value){ text.append(property).append(" = ").append(value). append("\n"); } public String getText() {

34
return text.toString(); } } -------------------public class XMLBuilder implements Builder{ private StringBuffer text;

CAPITOLUL 5. BUILDER

public XMLBuilder(){ text=new StringBuffer("<xml version="1.0">\n"); text.append("<properties>\n"); } public void addProperty(String property, String value){ text.append(String.format(" <%s>%s</%s>\n", property, value, property)); } public String getText(){ return text.toString()+"</properties>"; } } -------------------import java.io.IOException; public class TestBuilder { public static void main(String[] args) throws IOException { Director director=new Director("data.txt"); /*PropertiesBuilder propsBuilder=new PropertiesBuilder(); director.setBuilder(propsBuilder); director.parseText(); System.out.println(propsBuilder.getText());*/ XMLBuilder xmlBuilder =new XMLBuilder(); director.setBuilder(xmlBuilder); director.parseText(); System.out.println(xmlBuilder.getText()); } }

Capitolul 6

Prototype
Scop: Specic a tipul obiectelor ce urmeaz a a create cu o instant a prototip, si creeaz a obiecte prin copierea acestui prototip.

Motivare
Motivare: S a presupunem c a avem un joc care memoreaz a informat ii despre mai multe camere si u sile care exist a ntre aceste camere. Avem mai multe tipuri de camere si mai multe tipuri de u si. Se poate ca, la momentul rul arii, s a se stabileasc a pentru a folosite anumite tipuri de obiecte. Spre deosebire de Abstract Factory, de data aceasta nu avem familii de obiecte. Diversele tipuri de produse pot conviet ui mpreun a, deoarece el pot date prin interfet ele lor. In gura 6.1 am parametrizat clasa Game, chiar dac a indirect, n funct ie de tipurile obiectelor pe care le poate creea. Un exemplu de cod care poate folosi aceasta ierarhie de clase ar ar ata astfel: PrototypeManager proto=new PrototypeManager(new RedRoom(), new Door()); game.setPrototypeManager(proto); In interiorul metodei makeGame() a clasei Game nu se vor creea obiectele n mod direct ci prin intermediul clasei PrototypeManager ceea ce va face ca ntre tipurile de obiecte create s a existe o anumit a consistent a. 35

36

CAPITOLUL 6. PROTOTYPE

Figura 6.1: Motivare Prototype Dac a dorim s a modic am tipurile de obiecte care se vor crea, trebuie s a modic am o singur a linie, si anume cea n care este creat obiectul de tip PrototypeManager.

Alt a solut ie mai buna?


Pentru a ntelege mai bine acest sablon, trebuie s a ne g andim ce alte alternative am mai avea. Am putea de exemplu, n clasa Game s a construim c ate o metod a fac tory pentru ecare tip de produs. In continuare, pentru ecare combinat ie de produse am putea s a deriv am c ate o nou a clas a n care s a suprascriem numai metoda (metodele) care creeaz a obiectele si care trebuie modicate. Problema care apare este c a, cu c at avem mai multe tipuri de obiecte, cu at at vom avea mai multe clase derivate din clasa Game. Prin solut ia prezentat a anterior nu trebuie derivat a nici o clas a din clasa Game.

Aplicabilitate
Se folose ste acest sablon c and vrem ca un sistem s a e independent de modul n care produsele sale sunt create, compuse si reprezentate, si in plus:

37 C and clasele de instant iat sunt specicate la momentul rul arii, de exemplu, prin nc arcare dinamic a, sau Pentru a evita construirea de ierarhii de clase pentru fabrici de obiecte care se folosesc n paralel cu ierarhia de produse, sau C and instant e ale unei clase pot avea doar put ine combinat ii diferite de st ari. Poate mult mai convenabil s a instal am un num ar corespunz ator de prototipuri si s a le clon am, mai degrab a dec at a instant ia clasa manual, de ecare data cu starea potrivit a.

Structur a

Figura 6.2: Structura sablonului Prototype Folosirea acestui sablon are mai multe consecint e care merit a atent ia noastr a: Prin ad augarea unui prototype manager ca n exemplul prezentat anterior n sect iunea care motiveaz a utilizarea acestui sablon se poate, de exemplu, varia la momentul rul arii tipul obiectelor care sunt instant iate. Pentru ecare produs care este folosit trebuie implementat a o metod a de clonare, care s a permit a instant ierea lui. Eventual, se fac

38

CAPITOLUL 6. PROTOTYPE init ializ ari imediat dup a clonare. Acest lucru poate un dezavantaj n anumite situat ii. Se poate chiar ca n momentul n care compil am aplicat ia nu toate clasele corespunz atoare diferitelor produse s a e prezente n cale. Este posibil ca la momentul rul arii, anumite clase s a se nregistreze singure n PrototypeManager, prin folosirea nc arc arii dinamice a claselor, a sa cum am precizat n cazul sablonului Factory Method.

Partea II

S abloane structurale

39

Capitolul 7

Adapter
Scop: Converte ste interfat a unei clase ntr-o alt a interfat a pe care clientul o a steapt a. Permite conlucrarea unor clase care altfel n-ar putea lucra mpreun a din cauza interfet elor incompatibile.

Motivare
Motivare: S a presupunem c a avem un program de desenare care poate desena mai multe guri geometrice si texte. Pentru ecare tip de gur a avem c ate o clas a. Evident, un pic mai complicat a este clasa pentru desenarea textelor. S a presupunem c a deja avem o astfel de clas a, dar interfat a ei nu corespunde cu cea pe care o dorim, n cazul nostru Shape. Dup a cum se poate vedea n exemplu, solut ia este s a denim o nou a clas a, TextShape care s a adapteze clasa TextView. Acest lucru este prezentat n gura 7.1. Dup a cum se poate vedea, clasa TextShape are un atribut de tipul TextView, atunci c and este apelat a o metod a a clasei, de fapt se apeleaz a metoda (metodele) corespunz atoare din clasa TextView.

Alte solut ii mai bune?


Ce alte posibilit a ti mai avem? 41

42

CAPITOLUL 7. ADAPTER

Figura 7.1: Motivare utilitate Adapter Am putea s a construim o nou a clas a TextShape n care s a rescriem toat a funct ionalitatea, dar acest lucru ar putea foarte complex.

Aplicare
Se folose ste Adapter atunci c and: Vrem s a folosim o clas a existent a si interfat a ei nu se potrive ste cu cea pe care o a stept am. Vrem s a creem o clas a reutilizabil a care coopereaz a cu clase ne nrudite si pe care nu le putem anticipa (clase care nu au interfet e compatibile). (numai pentru object adapter) Trebuie folosite c ateva subclase existente dar este nepractic a adaptarea ec areia prin subclasare. Un object adapter poate adapta interfat a clasei p arinte.

Structur a
Dup a cum se poate observa avem dou a solut ii: Class Adapter - se deriveaz a clasa pe care vrem s a o adapt am si se implementeaz a interfat a la care vrem s a adaptam. Object Adapter - n clasa care realizeaz a adaptarea ret inem o referint a la obiectul adaptat. Clasa care face adaptarea trebuie s a implementeze interfat a la care se face adaptarea.

43

Figura 7.2: Structura Class Adapter

Figura 7.3: Structur a Object Adapter Observat ii: Dac a vrem s a adapt am mai multe clase care formeaz a o ierarhie de clase, trebuie s a folosim neap arat object adapter deoarece class adapter nu poate aplicat. Exista not iunea de pluggable adapters. Aceste adaptoare sunt ni ste clase care sunt deja concepute n interiorul unei clase pentru a putea introduce n aceast a clas a funct ionalitate din alte clase, care pot foarte diferite. Ideea care st a n spatele acestor tipuri de adaptoare este aceea c ao

44

CAPITOLUL 7. ADAPTER clas a este cu at at mai generic a cu c at se fac mai put ine presupuneri asupra obiectelor cu care clasa lucreaz a. Acesta este motivul pentru care, pentru anumite clase este util s a se construiasc a o anumit a adaptare a interfet elor.

Exemplu
S a presupunem c a avem o clas a Stiva si avem un program n care vrem s a folosim obiecte care implementeaz a interfat a Stack. Putem proceda n modurile urm atoare:
public interface Stack { void push(int x); int top(); int pop(); boolean isEmpty(); } public class Stiva { private int[] a; private int count; public Stiva(int dim) { a = new int[10]; } public Stiva() { this(10); } public void adauga(int x) { a[count++] = x; } public int varf() { return a[count - 1]; } public int scoate() { return a[--count]; } public boolean esteGoala() { return count == 0; } } public class StackObjectAdapter implements Stack { private Stiva s; public StackObjectAdapter(int dim) {

45
s = new Stiva(dim); } public StackObjectAdapter() { s = new Stiva(); } public void push(int x) { s.adauga(x); } public int top() { return s.varf(); } public int pop() { return s.scoate(); } public boolean isEmpty() { return s.esteGoala(); } } public class StackClassAdapter extends Stiva implements Stack { public StackClassAdapter(int dim) { super(dim); } public StackClassAdapter() { super(); } public boolean isEmpty() { return super.esteGoala(); } public int pop() { return super.scoate(); } public void push(int x) { super.adauga(x); } public int top() { return super.varf(); } } public class TestStack { public static void main(String[] args) { // Stack s=new StackObjectAdapter(); Stack s = new StackClassAdapter(); s.push(3); s.push(4); System.out.println(s.pop()); System.out.println(s.top());

46
} }

CAPITOLUL 7. ADAPTER

Capitolul 8

Bridge
Scop: Decuplarea unei abstract ii de implementarea ei astfel nc at cele dou a s a poat a varia independent.

Motivare
Motivare: O situat i n care ar avea sens s a folosim acest sablon ar dac a am avea o ierarhie de clase precum cea prezentat a n gura 8.1.

Figura 8.1: Motivare utilizare Bridge

Motivare
O solut ie pentru aceast a situat ie ar putea ar ata astfel: 47

48

CAPITOLUL 8. BRIDGE

Figura 8.2: Motivare utilizare Bridge

Alte solut ii mai bune?


Dup a cum am putut vedea, o problem a la care se aplic a sablonul de proiectare Bridge, poate rezolvat a si cu ajutorul subclas arii. Acest lucru ar presupune c a pentru ecare abstract ie vom avea c ate o implementare corespunz atoare ec arui tip de implementare. Dezavantajul acestei abord ari este c a num arul de clase cre ste foarte mult si ca nu se poate varia la momentul rul arii tipul implement arii.

Aplicare
Se aplic a acest sablon de proiectare atunci c and: Vrem s a evit am o legatur a permanent a ntre o abstract ie si implementarea ei. Poate nevoie de a sa ceva atunci c and implementarea poate aleas a si schimbat a la momentul rul arii. Atunci c and si abstract ia si implementarea trebuie s a e extensibile prin subclasare. S ablonul permite combinarea diferitelor abstract ii cu diferite implement ari si extinderea lor independent a. Schimb ari n partea de implementare nu ar trebui s a duc a la schimbarea codului client ilor (codul lor nu trebuie recompilat). C and avem o proliferare de clase ca n exemplul prezentat n sect iunea Motivare. O astfel de situat ie duce la necesitatea spargerii unui obiect n mai multe alte obiecte.

49 C and vrem s a partaj am o implementare ntre mai multe obiecte si acest lucru ar trebui ascuns de client.

Structur a

Figura 8.3: Structura sablonului Bridge Dup a cum se poate observa, sablonul Bridge este nc a un exemplu al principiilor care stau la baza majorit a tii sabloanelor de proiectare: Favorizarea compozit iei n dauna mo stenirii - se observ a c a partea de abstract ie ret ine o referint a la partea de implementare. C and ceva variaz a acel lucru trebuie ncapsulat - se poate s a avem o nou a abstract ie sau o nou a implementare. Acest lucru se poate realiza foarte u sor doar prin crearea unei noi clase derivate din Abstraction sau Implementor. Lucrul pe interfet e si nu pe implement ari - In codul pe care-l vom scrie, lucr am pe interfet ele Abstraction si Implementor.

Exemplu
Nu vom creea toate clasele pentru un exemplu care ar folosi sablonul Bridge, ci mai degrab a vom ncerca s a scriem doar o secvent a de cod care l-ar folosi:

50 WindowImp winImp=new XWindowImp(); IconWindow iw=new IconWindow(winImp); //folosire obiect ...

CAPITOLUL 8. BRIDGE

Capitolul 9

Fa cade
9.1 Scop si motivare

Scop: Ofer a o interfat a la un set de subinterfet e dintr-un subsistem. Fa cade dene ste o interfat a la nivel mai nalt care face subsistemul mai u sor de folosit. Motivare: S a presupunem c a dorim s a construim un sistem soft care dore ste s a permit a si trimiterea de mailuri. Pentru a putea scrie un mail, un client trebuie s a foloseasc a numeroase clase precum: Message, MessageBody, MessageHeader, Attachment etc. O port iune din acest sistem ar putea ar ata ca n gura 9.1. Totu si, se poate g andi o solut ie mai u soar a, precum cea din gura 9.2.

9.2

Alte solut ii mai bune?

Dup a cum am putut vedea, se pot folosi mai multe solut ii pentru rezolvarea aceleia si probleme. Totu si, cea de-a doua solut ie este mai bun a deoarece clientul nu va mai trebui s a lucreze cu foarte multe clase, av and n acest fel o independent a mai mare fat a de lucrurile interne care tin de acest subsistem. Astfel, prin introducerea unei indirect ari, s-a u surat accesul clientului la clasele din subsistem, el ind si mai independent fat a de sistemul respectiv. 51

52

CAPITOLUL 9. FAC ADE

Figura 9.1: Motivare utilitate Fa cade

Figura 9.2: Motivare utilitate Fa cade 2

9.3

Aplicare

Se aplic a acest sablon n situat ia n care se dore ste:

9.4. STRUCTURA

53

Vrem s a oferim o interfat a simpl a la un subsistem mai complex. Subsistemele de multe ori devin din ce n ce mai complexe pe m asur a ce evolueaz a si vrem s a ascundem acest lucru. O astfel de clas a ofer a o vedere mai simpl a a subsistemului care poate sucient a pentru majoritatea client ilor. Doar client ii foarte pretent io si au nevoie de mai mult. Sunt numeroase dependent e ntre client i si clasele de implement ari ale unor abstract ii. Se introduce Fa cade pentru a reduce cuplarea subsistemului de client i si alte subsisteme, promov and independent a si portabilitatea. Vrem s a scriem un sistem pe layere. Folosim o clasa Fa cade pentru a oferi un entry-level la nivelul ec arui subsistem. Se pot simplica leg aturile ntre ele prin comunicarea ntre diverse sisteme doar prin clasele lor Fa cade corespunz atoare.

9.4

Structur a

Figura 9.3: Structura sablonului Fa cade Ca si consecint e ale aplic arii acestui sablon, trebuie neap arat s a enumer am urm atoarele: Reduce num arul de clase de care trebuie s a stie client ii, ceea ce face folosirea subsistemului mai u soar a.

54

CAPITOLUL 9. FAC ADE Face clientul mult mai put in dependent de subsistemul cu care lucreaz a. Astfel, dac a este stabilit a o interfat a bun a, nu pentru orice modicare a subsistemului, trebuie realizat a o modicare a clientului. De fapt, prin acest lucru, dependent ele la compilare se pot reduce foarte mult. Acest sablon nu mpiedic a folosirea claselor din subsistem dac a acest lucru este neap arat necesar. Este ntr-un fel, un compromis ntre utilizabilitate si generalitate.

9.5

Exemplu

Acest sablon este at at de simplu de implementat, nc at nu vom prezenta nici un exemplu.

Capitolul 10

Composite
10.1 Scop si motivare

Scop: Compunerea obiectelor n structuri arborescente pentru a reprezenta ierarhii parte- ntreg. Composite permite client ilor s a trateze uniform obiecte individuale si obiecte compuse. Motivare: In cazul aplicat iilor grace dar si n cazul editorului Word, putem avea desene care cuprind mai multe guri geometrice. Pentru a putea trata mai u sor aceste desene este permis a compunerea mai multor guri geometrice n guri geometrice compuse. Problema care se pune este cum putem trata uniform astfel de guri geometrice? O solut ie este reprezentat a n gura 10.1.

Figura 10.1: Motivare utilizare Composite 55

56

CAPITOLUL 10. COMPOSITE Exist a si alte situat ii n care se folose ste sablonul Composite: In cadrul utilitarului JUnit avem teste, care sunt de dou a feluri: TestCase-uri (ca si gurile geometrice simple) precum si TestSuiteuri care pot cuprinde mai multe teste, care la r andul lor pot compuse din mai multe teste simple si compuse. Se poate folosi acest sablon atunci c and lucr am cu siere si directoare, sierele ind obiectele simple iar directoarele ind containerele care pot cont ine la r andul lor at at siere c at si alte directoare, n structuri oric at de complexe. Atunci c and avem interfet e grace complexe, putem folosi acest sablon f ar a s a ne d am seama. De exemplu, un panel poate cont ine mai multe alte paneluri precum si componente simple. La r andul lui, ecare panel poate cont ine mai multe alte paneluri si componente simple si tot asa.

10.2

Alte solut ii mai bune?

Este destul de complicat s a rezolv am problemele la care se aplic a Composite cu altfel de solut ii. Oricum, este posibil ca n cazul unor astfel de probleme s a folosim operatorul instanceof, dar acest lucru nu este elegant deoarece nu conduce la creearea unui cod exibil. Astfel, oric and ar trebui introdus a o nou a component a, ar trebui s a modic am codul n mai multe locuri.

10.3

Aplicare

Se aplic a acest sablon c and: Vrem s a reprezent am ierarhii de obiecte parte- ntreg. Client ii trebuie s a poat a ignora diferent ele ntre grupurile compuse de obiecte si obiectele individuale, cu alte cuvinte s a le trateze uniform.

10.4. STRUCTURA

57

10.4

Structur a

Figura 10.2: Structura sablonului Composite Folosirea sablonului Composite are c ateva consecint e importante: Face client ii mai simpli, deoarece trateaz a n mod uniform toate tipurile de obiecte din structura compus a. Este foarte u sor s a ad aug am un nou tip de component a. Trebuie doar s a creem o nou a clas a. Este mai greu de vericat diverse condit ii care trebuie respectate. Acestea pot vericate la momentul rul arii. In anumite situat ii are sens s a ret inem pentru o component a p arintele acesteia. Acesta va ret inut n clasa Component. In principiu, cu c at interfat a Component este mai bogat a cu at at este mai bine deoarece obiectele pot tratate c at mai uniform. Totu si sunt situat ii n care acest lucru este mai greu deoarece containerele si obiectele simple nu au chiar aceea si interfat a. Un caz particular l constituie modul n care sunt implementate operat iile pentru managementul copiilor. Ar trebui ele implementate n clasa Component sau n clasa Composite?

58

CAPITOLUL 10. COMPOSITE Prima variant a ofer a mai mult a transparent a, deoarece obiectele sunt tratate uniform, a doua variant a ofer a mai mult a sigurant a, deoarece nu se poate ca la momentul compil arii, la un obiect care este frunz a s a-i ad aug am componente.

10.5

Exemplu

public abstract class File { private String name; public File(String fileName) { name=fileName; } public String getName() { return name; } public void setName(String newName) { name=newName; } public abstract int getSize(); public void addFile(File f) {} public void removeFile(File f) {} } import java.util.*; public class Directory extends File { private List<File> files; public Directory(String name) { super(name); files=new ArrayList<File>(); } public int getSize() { int size=0; for(File f:files) size+=f.getSize();

10.5. EXEMPLU
return size; } public void addFile(File f) { files.add(f); } public void removeFile(File f) { files.remove(f); } } public class RegularFile extends File{ private int size; public RegularFile(String name, int size) { super(name); this.size=size; } public int getSize() { return size; } } public class TestComposite { public static void main(String[] args) { File f1=new RegularFile("a", 10); File f2=new RegularFile("b", 20); File dir1=new Directory("dir1"); dir1.addFile(f1); dir1.addFile(f2); File mainDir=new Directory("maindir"); File f3=new RegularFile("c", 30); mainDir.addFile(f3); mainDir.addFile(dir1); System.out.println(mainDir.getSize()); } }

59

60

CAPITOLUL 10. COMPOSITE

Capitolul 11

Decorator
11.1 Scop si motivare

Scop: Ata seaz a unui obiect responsabilit a ti adit ionale n mod dinamic. Decoratorii ofer a o alternativ a exibil a la subclasare pentru extinderea funct ionalit a tii. Motivare: Uneori dorim s a ad aug am anumite responsabilit a ti unor obiecte individuale, nu unor ntregi clase. O astfel de situat ie este, de exemplu, atunci c and dorim ca unei componente s a-i putem ad auga efectul de scroll sau de border, ca n gura 11.1. O solut ie neexibil a ar s a deriv am o clas a din clasa init ial a si s a-i ad aug am noua funct ionalitate, dar acest lucru nu mai permite clientului s a hot arasc a c and s a decoreze componenta.

Figura 11.1: Motivare utilitate Decorator 61

62

CAPITOLUL 11. DECORATOR

Dup a cum se poate vedea si vom explica n continuare, solut ia este s a includem componenta ntr-un alt obiect care s a aib a si noua funct ionalitate denit a. Obiectul care va ret ine referint a la vechiul obiect poart a numele de decorator. Solut ia unei astfel de probleme ar putea reprezentat a sub forma diagramei de obiecte din gura 11.1.

Figura 11.2: Diagrama de obiecte Practic se poate observa c a avem un obiect de tip TextView care este ncadrat de un ScrollDecorator si de un BorderDecorator. C and folosim aceast a structur a de obiecte se apeleaz a o metod a a clasei BorderDecorator care la r andul ei apeleaz a o metod a a clasei ScrollDecorator care n nal apeleaz a o metod a a clasei TextView. Fiecare decorator, nainte sau dup a apelul metodei corespunz atoare, mai face si un alt lucru.

Figura 11.3: Motivare utilitate Decorator Leg atura ntre obiectele simple si obiectele decorate se poate face la construirea obiectelor prin intermediul constructorilor, ca n urm atorul exemplu de cod.

11.2. ALTE SOLUT II MAI BUNE? VisualComponent ob=new BorderDecorator( new ScrollDecorator( new TextView())); ob.draw();

63

11.2

Alte solut ii mai bune?

Dup a cum am si precizat ntr-un paragraf precedent, o alt a solut ie ar putea s a cre am c ate o clas a pentru ecare tip de combinat ie posibil a. Totu si, av and n vedere c a se poate aplica un decorator si de mai multe ori, acest lucru ar putea conduce la un num ar foarte mare de clase. In plus, responsabilit a tile ad augate n-ar mai putea retrase dinamic si nici nu s-ar mai putea ad auga noi responsabilit a ti, dup a ce s-a instant iat o anumit a clas a.

11.3

Aplicare

Se aplic a sablonul Decorator: Pentru a ad auga responsabilit a ti la obiecte individuale dinamic s transparent (adic a f ar a a afecta alte obiecte). Pentru responsabillit a ti care pot retrase. C and extensia prin subclasare este nepractic a. Uneori un mare num ar de extensii independente este posibil si ar produce o explozie de clase pentru a suporta ecare combinat ie.

11.4

Structur a

Folosirea acestui sablon are mai multe consecint e: Prezint a o exibilitate mai mare dec at mo stenirea static a (se pot ad auga si ndep arta responsabilit a ti n mod dinamic). Intr-un design care folose ste Decorator vom avea mai multe obiecte mai mici, ceea ce face ntr-un anume fel, un pic mai greu de nt eles sistemul.

64

CAPITOLUL 11. DECORATOR

Figura 11.4: Structura sablonului Decorator Reprezint a o reprezentare a conceptului: changing the skin of an object vs. changing its guts, aceasta deoarece nu se schimb a nimic n interiorul obiectului ci doar la suprafat a, prin ncadrarea obiectului n decoratorul potrivit.

11.5

Exemplu

Acest sablon este foarte util, el ind folosit cu succes n mai multe limbaje. Una din situat iile n care modul lui de folosire este mai greoaie este n limbajul Java, atunci c and vorbim de operat iile de lucru cu siere si nu numai. Dup a cum vom vedea n continuare, n aceast a situat ie se regasesc lucrurile de care am vorbit nainte. V a readucet i aminte, faptul c a n limbajul Java nt alneam cod precum: BufferedReader buff=new BufferedReader( new InputStreamReader( System.in));

11.5. EXEMPLU

65

Figura 11.5: Structura unei p art i din Java I/O Pentru a nt elege mai bine structura sablonului se pune ntrebarea care sunt decoratorii n aceast a situat ie? Prezent am n continuare un alt exemplu care folose ste sablonul Decorator:
public interface Component { void operation(); } ---------public class ConcreteComponentA implements Component { public void operation() { System.out.println("ConcreteComponentA.operation()"); } } ---------public class ConcreteComponentB implements Component{ public void operation() { System.out.println("ConcreteComponentB.operation()"); } } ---------public class LineDecorator implements Component{ private Component component; public LineDecorator(Component component) { this.component=component; } public void operation() { System.out.println("------------------------------------------"); component.operation(); System.out.println("------------------------------------------");

66

CAPITOLUL 11. DECORATOR

} } --------public class PlusDecorator implements Component{ private Component component; public PlusDecorator(Component component) { this.component=component; } public void operation() { System.out.println("++++++++++++++++++++++++++++++++++++++++++"); component.operation(); System.out.println("++++++++++++++++++++++++++++++++++++++++++"); } } --------public class TestDecorator { public static void main(String[] args) { Component ldec=new LineDecorator(new ConcreteComponentA()); ldec.operation(); System.out.println(); Component pdec=new PlusDecorator(new LineDecorator( new ConcreteComponentB())); pdec.operation(); } }

Capitolul 12

Flyweight
12.1 Scop si motivare

Scop: Folosirea partaj arii pentru a suporta un mare num ar de obiecte ecient. Motivare: O situat ie n care acest sablon are sens s a e folosit este cea n care ne dorim s a construim un editor de texte. Dup a cum toat a lumea stie, avem caractere care sunt organizate pe linii, coloane si pagini. Astfel, ntr-un document de o dimensiune mai mare vom avea foarte multe obiecte, n care o mare cantitate de informat ie s-ar repeta. P an a si ni ste documente de o dimensiune relativ moderat a ar putea conduce la necesitatea creerii a zeci de mii de obiecte care sa ret in a numai caracterele.

Figura 12.1: Motivare utilitate Flyweight 67

68

CAPITOLUL 12. FLYWEIGHT

Un yweight este un obiect care este independent si care nu depinde de contextul n care este folosit. O distinct ie trebuie f acut a ntre dou a st ari posibile: starea intrinsec a - este starea intern a a unui obiect care poate partajat a ntre mai multe contexte si ea va ret inut a n yweight starea extrinsec a - este acea parte a obiectului care cont ine ceea ce poate varia si deci nu poate partajat. In cazul nostru putem spune ca pentru un astfel de caracter avem un anumit cod (stare intrinsec a) precum si un font, culoare, m arime etc. (starea extrinsec a). Astfel, se poate crea c ate un yweight pentru ecare liter a a alfabetului, urm and ca acea liter a s a e partajat a pentru ecare aparit ie a literei respective. O astfel de situat ie se poate reprezenta ca n gura 12.2.

Figura 12.2: Motivare utilitate Flyweight 2

12.2

Aplicare

Se aplic a acest sablon atunci c and toate condit iile urm atoare sunt adev arate: O aplicat ie folose ste un mare num ar de obiecte. Costurile de stocare sunt mari din cauza num arului de obiecte si a repetit iilor.

12.3. STRUCTURA O mare parte din starea obiectelor poate f acut a extrinsec a.

69

Multe grupuri de obiecte pot nlocuite prin relativ put ine obiecte partajate odat a ce starea extrinsec a este nl aturat a. Aplicat ia nu depinde de identitatea obiectelor. Din moment ce obiectele yweight pot partajate, testele de identitate vor returna adev arat pentru obiecte distincte conceptual.

12.3

Structur a

Figura 12.3: Structura sablonului Flyweight Folosirea acestui sablon are mai multe consecint e: Se poate ca folosirea Flyweight s a introduc a anumite costuri legate de transferarea, g asirea si/sau calcularea st arii extrinsece. Aceste costuri sunt totu si amortizate de cele care tin de utilizarea memoriei. Folosirea sablonului este cu at at mai util a cu c at se parteajeaz a mai put ine obiecte si cu c at partea comun a este mai mare.

12.4

Exemplu

import java.util.HashMap; import java.util.StringTokenizer; import java.util.Vector;

70

CAPITOLUL 12. FLYWEIGHT

public class FlyweightTest { public static void main(String[] args) throws Exception { Vector<String> empList = initialize(); FlyweightFactory factory = FlyweightFactory.getInstance(); for (int i = 0; i < empList.size(); i++) { String s = (String) empList.elementAt(i); StringTokenizer st = new StringTokenizer(s, ","); String name = st.nextToken(); String title = st.nextToken(); String division = st.nextToken(); FlyweightIntr flyweight = factory.getFlyweight(division); // associate the flyweight // with the extrinsic data object. VCard card = new VCard(name, title, flyweight); card.print(); } } private static Vector<String> initialize() { // for simplicity values are being hardcoded. Vector<String> v = new Vector<String>(); v.add("name1,title1,North"); v.add("name2,title2,South"); v.add("name3,title1,North"); v.add("name4,title3,East"); v.add("name5,title4,East"); v.add("name6,title2,East"); v.add("name7,title1,West"); v.add("name8,title3,West"); v.add("name9,title1,West"); v.add("name10,title6,South"); v.add("name11,title5,North"); v.add("name12,title1,North"); return v; } } class FlyweightFactory { private HashMap<String, FlyweightIntr> lstFlyweight;

12.4. EXEMPLU
private static FlyweightFactory factory = new FlyweightFactory(); private FlyweightFactory() { lstFlyweight = new HashMap<String, FlyweightIntr>(); } public synchronized FlyweightIntr getFlyweight(String divisionName) { if (lstFlyweight.get(divisionName) == null) { FlyweightIntr fw = new Flyweight(divisionName); lstFlyweight.put(divisionName, fw); return fw; } else { return (FlyweightIntr) lstFlyweight.get(divisionName); } } public static FlyweightFactory getInstance() { return factory; } // Inner flyweight class private class Flyweight implements FlyweightIntr { private String company; private String address; private String city; private String state; private String zip;

71

private void setValues(String cmp, String addr, String cty, String st, String zp) { company = cmp; address = addr; city = cty; state = st; zip = zp; } private Flyweight(String division) { // values are hard coded // for simplicity

72

CAPITOLUL 12. FLYWEIGHT


if (division.equals("North")) { setValues("CMP", "addr1", "cty1", } if (division.equals("South")) { setValues("CMP", "addr2", "cty2", } if (division.equals("East")) { setValues("CMP", "addr3", "cty3", } if (division.equals("West")) { setValues("CMP", "addr4", "cty4", } } public String getCompany() { return company; } public String getAddress() { return address; } public String getCity() { return city; } public String getState() { return state; } public String getZip() { return zip; }

"st1", "10000");

"st2", "20000");

"st3", "30000");

"st4", "40000");

}// end of Flyweight }// end of FlyweightFactory interface FlyweightIntr { public String getCompany(); public String getAddress(); public String getCity(); public String getState();

12.4. EXEMPLU
public String getZip(); } class VCard { String name; String title; FlyweightIntr objFW; public VCard(String n, String t, FlyweightIntr fw) { name = n; title = t; objFW = fw; } public void print() { System.out.println(name); System.out.println(title); System.out.println(objFW.getAddress() + "-" + objFW.getCity() + "-" + objFW.getState() + "-" + objFW.getZip()); System.out.println("----------------"); } }

73

74

CAPITOLUL 12. FLYWEIGHT

Capitolul 13

Proxy
13.1 Scop si motivare

Scop: Ofer a un surogat sau nlocuitor penru alt obiect, pentru a controla accesul la el. Motivare: Exist a anumite situat ii c and creearea unui obiect ar mult prea costisitoare. S a lu am exemplul unui editor de texte care cuprinde si imagini. In momentul n care deschidem un document cu sute de pagini, dac a ar trebui s a nc arc am toate imaginile la care se face referire n document, procesul ar putea destul de anevoios. O solut ie ar s a avem obiecte proxy, care ret in referint e la obiectele adev arate dar nu le ncarc a dec at atunci c and avem neap arat nevoie de ele. In cazul editorului de care am spus, este nevoie s a e nc arcat obiectul doar n momentul n care el trebuie desenat. De altfel, s-ar putea sa deschidem documentul, s a facem anumite operat iuni si multe din imagini s a nu e niciodata vizibile, motiv pentru care n-are sens s a e nc arcate din prima. Acest sablon este folosit si in cazul utilitarului Hibernate. Pentru cei care au lucrat cu Hibernate este bine stiut c a, mai ales odat a cu versiunea 3, obiectele asociate din alte tabele nu mai sunt inc arcate automat ci doar atunci c and acest lucru este specicat n sierele de mapare sau c and se apeleaz a explicit Hibernate.initialize(). S-a luat aceast a decizie pentru a gestiona c at mai bine resursele sistemului si a nu nc arca n mod inutil memoria RAM cu informat ii de care probabil nu va nevoie niciodat a. 75

76

CAPITOLUL 13. PROXY Acest mecanism poart a numele de lazy loading.

13.2

Aplicare

S ablonul Proxy este necesar atunci c and este nevoie de o referint a mai versatil a sau sosticat a la un anumit obiect. C ateva situat ii in care Proxy este aplicabil sunt urm atoarele: Un remote proxy este o reprezentare local a a unui obiect dintr-un alt spat iu de adres a (mai este numit si ambasador ). Un virtual proxy creeaz a obiectele scumpe la comand a. Un protection proxy controleaz a accesul la obiectul original. Sunt folositoare c and obiectele ar trebui s a aib a diferite drepturi de acces. O referint a inteligent a (smart reference) este o nlocuire a unui simplu pointer, ea mai face ceva atunci c and obiectul este accesat. Aceasta poate include: Num ararea referint elor la obiecte reale astfel nc at acestea s a poat a eliberate automat c and nu mai exista referint e (smart pointers) Inc arcarea unui obiect persistent n memorie c and este referent iat prima dat a. Vericarea faptului c a un obiect este blocat nainte de a-l accesa pentru a asigura faptul c a nici un alt obiect nu-l poate schimba.

13.3 13.4

Structur a Exemplul 1

Prezent am n aceast a sect iune modul n care s-ar putea realiza un copy on write proxy. Ne vom deni o structur a foarte mare care funct ioneaz a pe principiul tabelelor de dispersie si vom vedea ce se poate nt ampla c and mai mult i client i lucreaz a concomitent pe acela si obiect si cum putem ecientiza acest lucru.

13.4. EXEMPLUL 1

77

Figura 13.1: Structur a sablon Proxy O problem a poate ap area atunci c and pentru structura respectiv a sunt denite operat ii precum clonarea dar n acela si timp altcineva poate scrie noi obiecte n structur a. Problema poate ap area deoarece chiar n momentul n care cineva parcurge structura altcineva scrie si atunci nu putem spune c a avem o consistent a a datelor. O solut ie ar ca atunci c and cineva vrea s a parcurg a o astfel de structur a, el s a- si fac a o copie si doar dup a aceea s a o prelucreze, dar acest lucru ar putea nsemna s a se piard a prea mult timp inutil. Cel mai bine ar ca, doar atunci c and cineva scrie ntr-o astfel de structur a, lui s a i se construiasc a o nou a copie, client ii care au cerut doar s a vad a datele, put and lucra cu vechea variant a consistent a a valorilor din structura respectiv a. Avem urm atoarea aplicat ie n care clasa ReferenceCountedHashTable joac a rolul de proxy iar clasa LargeHashtable este clasa care va de fapt folosit a n aplicat ie. A se observa faptul c a atunci c and se incearc a introducerea unui obiect, atunci clasa se autocloneaz a, dar numai dac a exist a obiecte care deja folosesc acest obiect.
import java.util.Hashtable; // The proxy. public class LargeHashtable extends Hashtable { // The ReferenceCountedHashTable that this is a proxy for. private ReferenceCountedHashTable theHashTable; // Constructor public LargeHashtable() {

78

CAPITOLUL 13. PROXY


theHashTable = new ReferenceCountedHashTable();

} // Return the number of key-value pairs in this hashtable. public int size() { return theHashTable.size(); } // Return the value associated with the specified key. public synchronized Object get(Object key) { return theHashTable.get(key); } // Add the given key-value pair to this Hashtable. public synchronized Object put(Object key, Object value) { copyOnWrite(); return theHashTable.put(key, value); } // Return a copy of this proxy that accesses the same Hashtable. public synchronized Object clone() { Object copy = super.clone(); theHashTable.addProxy(); return copy; } // This method is called before modifying the underlying // Hashtable. If it is being shared then this method clones it. private void copyOnWrite() { if (theHashTable.getProxyCount() > 1) { synchronized (theHashTable) { theHashTable.removeProxy(); try { theHashTable = (ReferenceCountedHashTable) theHashTable .clone(); } catch (Throwable e) { theHashTable.addProxy(); } } } } // Private class to keep track of proxies sharing the hash table. private class ReferenceCountedHashTable extends Hashtable { private int proxyCount = 1;

13.5. EXEMPLUL 2
// Constructor public ReferenceCountedHashTable() { super(); } // Return a copy of this object with proxyCount set back to 1. public synchronized Object clone() { ReferenceCountedHashTable copy; copy = (ReferenceCountedHashTable) super.clone(); copy.proxyCount = 1; return copy; } // Return the number of proxies using this object. synchronized int getProxyCount() { return proxyCount; } // Increment the number of proxies using this object by one. synchronized void addProxy() { proxyCount++; } // Decrement the number of proxies using this object by one. synchronized void removeProxy() { proxyCount--; } } }

79

13.5

Exemplul 2

Se poate s a avem situat ii n care o anumit a clas a are o dimensiune foarte mare si nu vrem s a o nc arc am dec at atunci c and intr-adev ar avem nevoie de ea. Se poate face acest lucru folosind un virtual proxy ca n exemplul urm ator:

// The ILargeClass interface. public interface ILargeClass { public void method1(); public void method2();

80
}

CAPITOLUL 13. PROXY

// The LargeClass class. public class LargeClass implements ILargeClass { private String title; public LargeClass(String title) { this.title = title; } public void method1() {// Do method1 stuff. } public void method2() {// Do method2 stuff. } } // The LargeClassProxy class. public class LargeClassProxy implements ILargeClass { private ILargeClass largeClass = null; private String title; // Constructor public LargeClassProxy(String title) { this.title = title; } // Method 1. Create LargeClass instance if needed. public void method1() { if (largeClass == null) largeClass = createLargeClass(); largeClass.method1(); } // Method 2. Create LargeClass instance if needed. public void method2() { if (largeClass == null) largeClass = createLargeClass(); largeClass.method2(); } // Private method to create the LargeClass instance. private ILargeClass createLargeClass() { ILargeClass lc = null; try { // Get Class object for LargeClass.

13.5. EXEMPLUL 2
// When we do this, the class will be downloaded. Class c = Class.forName("LargeClass"); // Get Class objects for the LargeClass(String) constructor // arguments. Class[] args = new Class[] { String.class }; // Get the LargeClass(String) constructor. Constructor cons = c.getConstructor(args); // Create the instance of LargeClass. Object[] actualArgs = new Object[] { title }; lc = (ILargeClass) cons.newInstance(actualArgs); System.out.println("Creating instance of LargeClass"); } catch (Exception e) { System.out.println("Exception: " + e); } return lc; } }

81

82

CAPITOLUL 13. PROXY

Partea III

S abloane comportamentale

83

Capitolul 14

Chain of Responsability
14.1 Scop si motivare

Scop: Evitarea cupl arii emit atorului unei cereri de cel care o prime ste, prin oferirea mai multor obiecte a sansei de a trata acea cerere. Se nl ant uiesc mai multe obiecte si se transmite cererea de-a lungul lant ului p an a c and un obiect o poate trata. Motivare: In anumite situat ii vrem s a putem trimite o cerere, f ar a a specica n momentul n care trimitem acea cerere cine este obiectul ns arcinat cu tratarea ei. Astfel, cererea este transmis a unui prim obiect, care dac a poate o trateaz a ntr-un anume fel, dac a nu o trimite mai departe altui obiect. Acela si lucru se nt ampl a si cu acesta. Se tot repet a pa sii p an a c and, e cererea este tratat a e s-a terminat lant ul de obiecte. Un astfel de exemplu, poate considerat atunci c and d am click pe semnul ? - help si pe un anumit element de pe o fereastr a. Dac a obiectul cel mai de sus poate trata cererea atunci se a seaz a informat ii despre el, dac a nu, cererea este trimis a obiectului care-l cont ine, si tot a sa p an a se ajunge la un obiect care poate trata cererea respectiv a. Reprezent am o situat ie de acest tip n diagrama 14.1. Pentru a asigura faptul c a acest lucru se nt ampl a transparent, trebuie s a avem o interfat a comun a a tuturor claselor, interfat a reprezentat a cu ajutorul clasei abstracte HelpHandler. Din aceast a diagram a se poate de asemenea u sor observa faptul c a ecare obiect ret ine o referint a la un obiect handler, care poate trata mai 85

86

CAPITOLUL 14. CHAIN OF RESPONSABILITY

departe cererea n cazul n care obiectul nostru nu poate face acest lucru.

Figura 14.1: Motivare utilitate Chain of Responsability

14.2

Aplicare

Se aplic a acest sablon atunci c and: Mai mult de un obiect poate trata o cerere si handlerul este necunoscut a priori. Vrem s a transmitem o cerere unui obiect f ar a a-l preciza explicit. Setul de obiecte care poate trata cererea ar trebui s a poat a specicat dinamic.

14.3

Structur a

Principalele consecint e ale aplic arii acestui sablon sunt: Reduce cuplarea prin faptul c a, atunci c and se transmite o cerere nu se poate sti imediat cine va obiectul care o va trata. Mai mult dec at at at nu se poate sti nici m acar tipul lui.

14.3. STRUCTURA

87

Figura 14.2: Structur a sablon Chain of Responsability Permite o mare exibilitate, deoarece modul n care sunt tratate cererile poate varia inclusiv la momentul rul arii n funct ie de leg aturile care exist a ntre obiecte. Se poate s a avem situat ii n care cererea s a nu e primit a de nimeni. Acest lucru se poate nt ampla atunci c and avem o gre seal a sau c and am programat cu g andul la facilit a ti ulterioare. Cererile pot transmise prin intermediul unor constante sau prin intermediul unor obiecte.

88

CAPITOLUL 14. CHAIN OF RESPONSABILITY

Capitolul 15

Command
15.1 Scop si motivare

Scop: Incapsuleaz a o cerere ca un obiect, permit and parametrizarea client ilor cu diferite cereri, punerea n coad a sau logging-ul cererilor, precum si suportarea operat iilor undoable. Motivare: De multe ori, ntr-o aplicat ie avem un meniu prin intermediul c aruia dorim s a putem efectua diverse operat ii, f ar a ca meniul nsu si s a stie cine este cel care prime ste comanda sau care este comanda executat a. In aceste situat ii comanda este ncapsulat a ntr-un obiect, care are o metod a execute(), n interiorul c areia putem s a denim ceea ce vrem s a facem. Din punctul de vedere al componentei meniu este doar un obiect care are o metoda execute(). Acest lucru asigur a faptul c a am creat un meniu c at se poate de general. Aceast a situat ie este prezentat a n gura 15.1. Dup a cum se poate vedea ecare menu item este congurat cu o instant a a interfet ei Command. C and un utilizator execut a click pe un meniu, automat se apeleaz a metoda execute() a obiectului Command corespunz ator, f ar a ca meniul s a poat a con stient de obiectul care a generat act iunea sau de obiectul ns arcinat cu efectuarea ei. Se poate chiar combina sablonul Command cu sablonul Composite pentru a se crea macrocomenzi. Astfel, dup a cum ne aducem aminte, o macrocomand a ar putea alc atuit a din mai multe macrocomenzi si mai 89

90

CAPITOLUL 15. COMMAND

Figura 15.1: Motivare utilitate Command multe comenzi simple.

15.2

Aplicare

Se folose ste sablonul Command atunci c and vrem s a: Parametriz am obiecte prin act iuni pe care ele trebuie s a le poat a face. S a specic am, punem n coad a si s a execut am cereri la momente diferite. Un obiect Command poate avea o viat a independent a de cererea init ial a. Dac a primitorul cererii poate reprezentat ntr-un spat iu de adres a independent, atunci se poate ca el s a primeasc a cererea ntr-un proces diferit si s a o rezolve acolo. Putem suporta operat ia undo. Operat ia execute() a lui Command poate stoca stare pentru a putea reface operat ia. Interfat a Command ar trebui s a aib a o metod a unexecute() care s a aib a efectul invers lui execute(). Comenzile executate ar trebui stocate ntr-un history list. Suport am jurnalizarea care ar permite ca schimb arile s a e reaplicate n cazul unui sistem crash. Ar putea necesita mbog a tirea interfet ei Command si cu operat ii de salvare/ nc arcare. Structur am un sistem asupra operat iilor la nivel nalt construite pe baza operat iilor primitive. Aceast a structur a este comun a n siste-

15.3. STRUCTURA

91

mele care dorim s a poat a permite utilizarea tranzact iilor. Commandurile au toate accea si interfat a ceea ce ar permite modelarea la fel a tuturor tranzact iilor.

15.3

Structur a

Figura 15.2: Structur a sablon Command Ca si consecint e ale acestui sablon, remarc am: Decupleaz a obiectul care face o cerere de obiectul care stie cum s a trateze acea cerere. Este foarte u sor s a se adauge noi comenzi, neind nevoie de schimbarea nici unei clase existente. Exist a creat cadrul pentru folosirea macrocomenzilor. Ofer a cadrul pentru implementarea operat iilor de undo. Pentru a putea face acest lucru, de multe ori este nevoie ca obiectele de tip Command s a poat a ret ine informat ii de stare suplimentare. Mai mult, este nevoie s a ret inem o list a de obiecte de tip Command cu ajutorul c areia s a putem reface anumite operat ii. Acest lucru ar putea posibil dac a, n plus, obiectele de tip Command ar nregistrate si cu o operatie unexecute().

92

CAPITOLUL 15. COMMAND

15.4

Exemplu

In nal prezent am un mic exemplu de utilizare al acestui sablon. Avem o aplicat ie care trebuie s a tot execute mai multe task-uri, ecare task av and o anumit a frecvent a de execut ie. Componenta care se ocup a de executarea task-urilor nu trebuie s a cunoasc a tipul componentelor de tip Task pe care le ret ine. Mai mult, aceasta component a nu stie nimic despre operat iile care vor efectuate. Prezent am diagrama acestei aplicat ii in gura 15.3.

Figura 15.3: Diagrama aplicat iei exemplu Avem urm atorul cod:
public interface Task { public void performTask(); } public class Task1 implements Task{ public void performTask() { System.out.println("First task..."); } } public class Task2 implements Task{ public void performTask() { System.out.println("Second task..."); } }

15.4. EXEMPLU

93

public class TaskEntry { private Task task; private long repeatInterval; // How often task should be private long timeLastDone; // Time task was last done public TaskEntry(Task task, long repeatInterval) { this.task = task; this.repeatInterval = repeatInterval; this.timeLastDone = System.currentTimeMillis(); } public Task getTask() { return task; } public void setTask(Task task) { this.task = task; } public long getRepeatInterval() { return repeatInterval; } public void setRepeatInterval(long ri) { this.repeatInterval = ri; } public long getTimeLastDone() { return timeLastDone; } public void setTimeLastDone(long t) { this.timeLastDone = t; } public String toString() { return (task + " to be done every " + repeatInterval + " ms; last done " + timeLastDone); } } import java.util.*; public class TaskMinder extends Thread { private long sleepInterval; // How often the TaskMinder should

94

CAPITOLUL 15. COMMAND

// check for tasks to be run private ArrayList<TaskEntry> taskList; // The list of tasks public TaskMinder(long sleepInterval, int maxTasks) { this.sleepInterval = sleepInterval; taskList = new ArrayList<TaskEntry>(maxTasks); start(); } public void addTask(Task task, long repeatInterval) { long ri = (repeatInterval > 0) ? repeatInterval : 0; TaskEntry te = new TaskEntry(task, ri); taskList.add(te); } public Iterator<TaskEntry> getTasks() { return taskList.iterator(); } public long getSleepInterval() { return sleepInterval; } public void setSleepInterval(long si) { this.sleepInterval = si; } public void run() { while (true) { try { sleep(sleepInterval); long now = System.currentTimeMillis(); Iterator<TaskEntry> e = taskList.iterator(); for(TaskEntry te:taskList) { if (te.getRepeatInterval() + te.getTimeLastDone() < now) { te.getTask().performTask(); te.setTimeLastDone(now); } } } catch (Exception e) { System.out.println("Interrupted sleep: " + e); } } } }

15.4. EXEMPLU
public class TestTask { public static void main(String args[]) { TaskMinder tm = new TaskMinder(500, 100); Task1 t1=new Task1(); tm.addTask(t1, 800); Task t2=new Task2(); tm.addTask(t2, 3000); } }

95

96

CAPITOLUL 15. COMMAND

Capitolul 16

Interpreter
16.1 Scop si motivare

Scop: In situat ia n care avem o gramatic a, dene ste reprezentarea ei mpreun a cu un interpretor care folose ste aceast a reprezentare pentru a interpreta propozit ii ale acelui limbaj. Motivare: Prezent am, n continuare, o gramatic a care dene ste un set de expresii regulate: expression::= literal | alternation | sequence | repetition | (expression) alternation::=expression | expression sequence::=expression & expression repetition::=expression * literal::=a | b ... (a | b ...)* Simbolul expression este simbolul de start, iar simbolul literal este un simbol terminal, care dene ste cuvinte simple. S ablonul Interpreter folose ste c ate o clas a pentru a reprezenta ecare regul a n parte, ca n exemplul urm ator:

97

98

CAPITOLUL 16. INTERPRETER

Figura 16.1: Motivare utilitate Interpreter De exemplu, expresia regulata raining AND ((dogs OR cats) *) ar putea ar ata astfel:

Se poate crea un interpretor pentru o astfel de expresie prin denirea operat iei interpret() pentru ecare subclas a a lui RegularExpression.

16.2. APLICARE

99

Aceast a operat ie ar putea primi un parametru de tip Context care s a reprezinte contextul n care se interpreteaz a expresia. Acesta ar putea cont ine sirul care trebuie interpretat, precum si informat ii legate de c at anume din sir a fost deja interpretat. Fiecare subclas a implementeaz a operat ia interpret() pentru a verica urm atoarea parte din sirul de intrare, pe baza contextului curent astfel: LiteralExpression va verica dac a intrarea se potrive ste cu un literal AlternationExpression va verica dac a intrarea se potrive ste cu una din alternative RepetitionExpression va verica dac a intrarea are mai multe repetit ii ale expresiei care ar trebui s a se repete etc.

16.2

Aplicare

Se folose ste sablonul Interpreter atunci c and avem un limbaj de interpretat si c and se pot reprezenta instruct iunile limbajului sub forma unor arbori abstract i de sintax a. S ablonul este folosit cel mai bine c and: Gramatica este simpl a. Pentru gramatici mari, ierarhia de clase pentru gramatic a devine mare si greu de controlat. In aceste situat ii se folosesc diferite tool-uri care reprezint a alternative mai bune. Ele pot interpreta expresii f ar a a genera arbori abstract i de sintax a ceea ce poate duce la economia de spat iu si timp. Ecient a nu este un aspect critic. Cele mai eciente interpretoare nu sunt de obicei implementate prin interpretarea unor arbori de parsare ci mai degrab a prin translatarea int ai sub o alt a form a. De exemplu, expresiile regulate sunt adesea transformate n ma sini de stare. Dar chiar si atunci translatorul poate implementat folosind sablonul Interpreter, ceea ce face si atunci sablonul aplicabil.

16.3

Structur a

In aceast a diagram a, clasa Context ret ine informat ii globale pentru interpretor.

100

CAPITOLUL 16. INTERPRETER

Figura 16.2: Structur a sablon Interpreter Trebuie precizat c a ordinea n care se execut a operat iile este urm atoarea: Clientul construie ste sau i este transmis un arbore care cont ine elemente neterminale si terminale de tipul celor de mai sus. Apoi, clientul init ializeaz a contextul si invoc a operat ia interpret(). Fiecare nod neterminal calculeaz a valoarea expresiei n funct ie de rezultatele returnate de ecare subexpresie. Operat iile interpret() folosesc contextul pentru a stoca si accesa starea interpretorului. Ca urmare a folosirii acestui sablon avem si c ateva consecint e importante: Este simplu de schimbat si extins gramatica. Acest lucru este evident, deoarece, oric and se dore ste ad augarea unei noi operat ii acest lucru se poate face prin crearea unei noi clase. Implementarea gramaticii este destul de u soar a, n parte si pentru c a implement arile seam an a. S ablonul este mai greu de folosit n cazul gramaticilor cu foarte multe reguli.

16.4. EXEMPLU

101

16.4

Exemplu

Prezent am, n cele ce urmeaz a un mic exemplu de utilizare al acestui sablon. Vom construi un interpretor de expresii booleene. Aplicat ia noastr a va recunoa ste urm atoarea gramatic a:
BooleanExp::=VariableExp | Constant | OrExp | AndExp | NotExp | XorExp | ( BooleanExp ) AndExp::=BooleanExp and BooleanExp OrExp::=BooleanExp or BooleanExp XorExp::=BooleanExp xor BooleanExp NotExp::=not BooleanExp Constant::= true | false VariableExp::= a | b | ... | z

In primul r and, denim interfat a comun a tuturor expresiilor booleene si anume BooleanExp, dup a care vom deni si clasele care o implementeaz a.
public interface BooleanExp { boolean interpret(Context c); } import java.util.*; public class Context { private Hashtable<String, Boolean> var; public Context() { var=new Hashtable<String, Boolean>(); } public boolean lookup(String varName) { if(!var.contains(varName)) throw new RuntimeException("Variable not defined: "+varName); return var.get(varName); } public void assign(String varName, boolean value) { var.put(varName, value); } }

102

CAPITOLUL 16. INTERPRETER

public class VariableExp implements BooleanExp { private String name; public VariableExp(String name) { this.name=name; } public boolean interpret(Context c) { return c.lookup(name); } }

public class AndExp implements BooleanExp { private BooleanExp op1, op2; public AndExp(BooleanExp op1, BooleanExp op2) { this.op1=op1; this.op2=op2; } public boolean interpret(Context c) { return op1.interpret(c) && op2.interpret(c); } } public class OrExp implements BooleanExp{ private BooleanExp op1, op2; public OrExp(BooleanExp op1, BooleanExp op2) { this.op1=op1; this.op2=op2; } public boolean interpret(Context c) { return op1.interpret(c) || op2.interpret(c); } } public class NotExp { private BooleanExp op; public NotExp(BooleanExp op) { this.op=op; }

16.4. EXEMPLU
public boolean interpret(Context c) { return !op.interpret(c); } } public class XorExp { private BooleanExp op1, op2; public XorExp(BooleanExp op1, BooleanExp op2) { this.op1=op1; this.op2=op2; } public boolean interpret(Context c) { boolean x=op1.interpret(c); boolean y=op2.interpret(c); return ((!x)&& y)||(x && (!y)); } } public class TestBooleanExp { public static void main(String[] args) { //Definirea expresiei booleene VariableExp ve1=new VariableExp("x"); VariableExp ve2=new VariableExp("y"); AndExp ae=new AndExp(ve1, ve2); OrExp oe=new OrExp(ve1, ae); //Setarea variabilelor din context Context c=new Context(); c.assign("x", true); c.assign("y", false); //Interpretarea expresiei System.out.println(ae.interpret(c)); } }

103

104

CAPITOLUL 16. INTERPRETER

Capitolul 17

Iterator
17.1 Scop si motivare

Scop: Ofer a o modalitate de a accesa elementele unui obiect agregat secvent ial f ar a a-i expune reprezentarea sa intern a. Motivare: Un obiect compus precum o list a ar trebui s a ofere un anumit mod n care obiectele care sunt cont inute de el s a poat a parcurse f ar a a se expune structura intern a a obiectului. Se poate, de exemplu s a vrem s a avem mai multe moduri de a traversa un obiect f ar a a dori s a complic am foarte mult interfat a acelei clase. De asemenea, s-ar putea s a dorim s a facem mai mult de o singur a traversare la un moment dat. Acest lucru se poate face cu ajutorul unui obiect special numit iterator (cursor) care are rolul de a prezenta o interfat a cu ajutorul c areia se poate parcurge lista si de a ment ine evident a obiectului curent si a obiectelor care deja au fost parcurse. Dac a se poate s a parcurgem structuri de date diferite cu aceea si metod a de iterare atunci avem o iterare polimorc a. Dup a cum se stie acest mecanism este foarte utilizat at at n Java c at si in C++ ( n STL - Standard Template Library). In Java, de exemplu, pentru a putea parcurge un ArrayList ar trebui s a scriem cod precum urm atorul: Iterator<Persoana> it = list.iterator(); while(it.hasNext()) { 105

106 Persoana p=it.next(); //prelucrare obiect.... }

CAPITOLUL 17. ITERATOR

Figura 17.1: Motivare utilitate Iterator Dup a cum se poate u sor observa, am f acut obiectul agregat responsabil pentru crearea obiectului iterator, prin metoda iterator(). Aceast a metod a este o metod a care ilustreaz a folosirea sablonului Factory Method.

17.2

Aplicare

Se folose ste acest sablon atunci c and: Pentru a accesa cont inutul unui obiect agregat f ar a a-i expune reprezentarea sa intern a. Pentru a suporta mai multe tipuri de travers ari a obiectelor agregate. Pentru a oferi o interfat a uniform a la traversarea diverselor structuri agregate (adic a pentru a suporta iterarea polimorc a).

17.3

Structur a

In momentul n care se dore ste implementarea unui iterator, se poate s a nt alnim mai multe situat ii deosebite:

17.4. EXEMPLU

107

Figura 17.2: Structur a sablon Iterator Cine controleaz a iterarea? iteratori interni. Se poate s a avem iteratori externi si

Un iterator extern este un iterator n care trecerea de la un element la altul se face n mod explicit de c atre client. Un iterator intern este un iterator n care nu se nt ampl a acest lucru. Unui astfel de iterator i se d a operat ia care trebuie f acut a si el face singur toat a traversarea. Cine dene ste algoritmul de traversare? De si n general algoritmul este denit n iterator, se poate nt ampla ca algoritmul de traversare s a e denit si n obiectul agregat, iteratorul ind folosit doar pentru a ret ine informat ii despre locul n care s-a ajuns cu iterarea. Atunci spunem c a avem de-a face cu un cursor. Un iterator robust este un iterator care asigur a faptul c a stergerea si introducerea de elemente nu afecteaz a traversarea, f ar a a lucra pe copii ale colect iilor.

17.4

Exemplu

In sect iunea dedicat a exemplelor vom vedea cum se poate implementa n limbajul Java o colect ie ale c arei elemente s a poat a parcurse folosind un Iterator. Pentru a realiza acest lucru este necesar ca acea clas a s a aib a o metod a iterator() care s a returneze un obiect care implementeaz a interfat a

108

CAPITOLUL 17. ITERATOR

Iterator. Mai mult, vrem ca obiectele colect iei pe care o vom crea s a poat a parcurse folosind un for-each. Pentru ca acest lucru s a e posibil colect ia noastr a trebuie s a implementeze interfat a Iterable. Cele 2 interfet e sunt prezentate n slide-ul urm ator.
public interface Iterator<T> { boolean hasNext(); T next(); void remove(); //operatie optionala } public interface Iterable<T> { Iterator<T> iterator(); }

Interfat a Iterator face parte din pachetul java.util n timp ce interfat a Iterable face parte din pachetul java.lang. Cu ajutorul unui obiect de tip Iterator se pot parcurge obiectele din cadrul colect iei, n timp ce cu un obiect care implementeaz a interfat a Iterable se poate folosi foreach pentru a-i parcurge elementele. Prezent am n cele ce urmeaz a modul n care ar putea implementat a o clasa Stiva care folose ste conceptele prezentate anterior.
import java.util.Iterator; public class Stiva<T> implements Iterable<T>{ private Node varf; public boolean isEmpty() { return varf==null; } public void push(T info) { Node node=new Node(info, varf); varf=node; } public T top() { if(isEmpty())

17.4. EXEMPLU
throw new RuntimeException("Stack Empty Exception"); return varf.info; } public T pop() { if(isEmpty()) throw new RuntimeException("Stack Empty Exception"); T info=varf.info; varf=varf.next; return info; } public Iterator<T> iterator() { return new Iterator<T>() { private Node currentNode = varf; public boolean hasNext() { return currentNode!=null; } public T next() { T info=currentNode.info; currentNode=currentNode.next; return info; } public void remove() { throw new UnsupportedOperationException(); } }; } private class Node { private T info; private Node next; public Node(T info, Node next) { this.info=info; this.next=next; } } /*public Iterator<T> iterator() { return new StivaIterator(); }

109

110

CAPITOLUL 17. ITERATOR

private class StivaIterator implements Iterator<T>{ private Node currentNode; public StivaIterator() { currentNode=varf; } public boolean hasNext() { return currentNode!=null; } public T next() { T info=currentNode.info; currentNode=currentNode.next; return info; } public void remove() { throw new UnsupportedOperationException(); } }*/ }

Aceast a structur a poate folosit a astfel:


public class TestStiva { public static void main(String[] args) { Stiva<String> st=new Stiva<String>(); st.push("crina"); st.push("viorel"); st.push("florin"); System.out.println("In varful stivei: "+st.top()); System.out.println("Continutul stivei: "); for(String s:st) System.out.print(s+" "); } }

Capitolul 18

State
18.1 Scop si motivare

Scop: Permite unui obiect s a- si schimbe comportamentul atunci c and starea sa intern a se modic a. Obiectul va p area c a si-a schimbat clasa. Motivare: S a consider am situat ia n care am avea o clas a TCPConnection. Ea se poate aa ntr-una din st arile: established, listening sau closed. Bine nt eles, n funct ie de starea n care se a a, aceast a clas a r aspunde diferit la comenzile primite din partea altor obiecte. Astfel, ca urmare a apelului metodei open(), de exemplu, se nt ampl a lucruri diferite n funct ie de starea curent a. Ideea acestui sablon este de a deni o nou a clas a (interfat a) TCPState, care s a ret in a lucrurile comune tuturor st arilor, dup a care s a denim pentru ecare stare n parte c ate o clas a. Clasa TCPConnection va ret ine o referint a la un obiect care implementeaza interfat a, urm and ca la apelul oric arei metode, de fapt s a se apeleze metoda corespunz atoare din obiectul ret inut. Atunci c and se schimb a starea curent a a obiectului TCPConnection el va referi alt a instant a corespunz atoare noii st ari.

18.2

Aplicare

Se aplic a sablonul State atunci c and: Comportamentul unui obiect depinde de starea sa si trebuie s a- si schimbe comportamentul la rulare n funct ie de starea sa. 111

112

CAPITOLUL 18. STATE

Figura 18.1: Motivare utilitate State Operat iile obiectului au multe p art i condit ionale mari care depind de starea obiectului. Adesea starea este reprezentat a prin una sau mai multe enumerari. Aproape mereu, mai multe operat ii vor cont ine aceea si instruct iune condit ional a complex a. Dup a cum vom vedea sablonul State pune ecare condit ie n propria sa clas a. Acest lucru permite tratarea ec arei st ari independent de celelalte st ari.

18.3

Structur a

Figura 18.2: Structur a sablon State

18.4. EXEMPLU Folosirea sablonului State poate avea mai multe consecint e:

113

S ablonul State pune tot codul corespunz ator unei condit ii ntr-un obiect separat. Acest lucru permite ad augarea foarte u soar a de noi st ari sau modicarea tranzit iilor existente. Alternativa ar s a folosim subclasarea clasei Context sau s a utiliz am variabile care n funct ie de valoarea lor, cu ajutorul unor instruct iuni condit ionale s a permit a stabilirea st arii curente. Avem un mic dezavantaj deoarece vom folosi mai multe clase, dar oricum acest lucru este de preferat n dauna utiliz arii unor instruct iuni condit onale mari, care n timp devin greu de nt eles. Tranzit iile de la o stare la alta sunt mult mai explicite. In anumite situat ii, atunci c and starea nu are date pe care le ret ine, ea poate partajat a de mai multe obiecte. Este foarte important cine determina modul de trecere de la o stare la alta. S ablonul State nu specic a clar acest lucru. Se poate ca obiectul Context s a e responsabil de acest lucru. Se poate ca starea ns a si s a poat a, prin intermediul unei metode a obiectului Context s a stabileasc a starea care o va succeda. Aceast a abordare este mai exibil a. O alternativ a la utilizarea sablonului State ar putea folosirea table lookup-urilor. Intr-o astfel de tabel a pe baza unei anumite st ari curente si a unei intr ari se poate stabili trecerea la starea urm atoare. Diferent a primordial a ntre cele dou a abord ari este c a n cazul sablonului State se pune accentul pe individualizarea ec arei st ari, n timp ce n cazul tabelelor se pune mare accent pe realizarea tranzit iilor de la o stare la alta.

18.4

Exemplu

public interface State { int executeSQL(String sql); Object executeScalar(String sql);

114
} public class AutoCommitState implements State{

CAPITOLUL 18. STATE

public int executeSQL(String sql) { System.out.println("executeSQL() in auto commit state..."); return 0; } public Object executeScalar(String sql) { System.out.println("executeScalar() in auto commit state..."); return null; } } public class TransactionalState implements State{ public int executeSQL(String sql) { System.out.println("executeSQL() in transactional state..."); return 0; } public Object executeScalar(String sql) { System.out.println("executeScalar() in transactional state..."); return null; } } public class Session { private State state; private boolean isInTransaction; private State AUTO_COMMIT=new AutoCommitState(); private State TRANSACTIONAL=new TransactionalState(); public Session() { setState(AUTO_COMMIT); isInTransaction=false; } private void setState(State s) { this.state=s; }

18.4. EXEMPLU

115

public void beginTransaction() { if(isInTransaction) throw new RuntimeException("Already in transaction..."); isInTransaction=true; setState(TRANSACTIONAL); } public void endTransaction() { if(!isInTransaction) throw new RuntimeException("Already not in transaction..."); System.out.println("Commiting the transaction..."); isInTransaction=false; setState(AUTO_COMMIT); } public void rollbackTrasaction() { if(!isInTransaction) throw new RuntimeException("Already not in transaction..."); System.out.println("Roll back the transaction..."); isInTransaction=false; setState(AUTO_COMMIT); } public int executeSQL(String sql) { return state.executeSQL(sql); } public Object executeScalar(String sql) { return state.executeScalar(sql); } } public class TestState { public static void main(String[] args) { Session sess=new Session(); sess.executeSQL("update persoane set nume="gigi" where varsta=20"); sess.beginTransaction(); sess.executeSQL("update persoane set nume="gigi" where varsta=20"); sess.endTransaction(); } }

116

CAPITOLUL 18. STATE

Capitolul 19

Strategy
19.1 Scop si motivare

Scop: Dene ste o familie de algoritmi, l ncapsuleaz a pe ecare si i face interschimbabili. Permite varierea independent a a algoritmului de clasa care l utilizeaz a. Motivare: Exist a numero si algoritmi pentru spargerea unui stream n linii. Introducerea algoritmului n clasa care-l folose ste nu este cea mai bun a solut ie din mai multe motive: Client ii vor deveni cu at at mai complec si cu c at num arul algoritmilor suportat i va mai mare. Nu tot i algoritmi vor folosit i de ecare dat a si nu vrem s a suport am algoritmi care s-ar putea s a nu e folosit i. Este dicil de ad augat noi algoritmi si de a-i varia pe cei existent i f ar a a nevoie s a modic am codul curent. Principiul pe care vrem s a-l respect am este principiul Open-Closed care spune c a: Un sistem trebuie s a e deschis la extensie (s a e construit astfel nc at s a permit a ad augarea de noi funct ionalit a ti). Un sistem trebuie s a e inchis la modic ari (ad augarea noilor funct ionalit a ti nu trebuie s a necesite schimbarea codului existent). 117

118

CAPITOLUL 19. STRATEGY

Figura 19.1: Motivare utilitate Strategy Se poate rezolva aceast a situat ie prin crearea unei interfet e care s a reprezinte un algoritm, iar pentru ecare implementare propriu zis a a algoritmului s a avem c ate o clas a separat a. Clasa care folose ste algoritmul va ret ine o referint a la obiectul care va cont ine algoritmul propriu-zis. Avantajul acestei abord ari este c a algoritmul poate varia la momentul rul arii.

19.2

Aplicare

Se folose ste sablonul Strategy atunci c and: Mai multe clase nrudite difer a numai prin comportament. Strategiile ofer a o modalitate de congurare a unei clase cu unul din mai multe comportamente. Avem variante diferite ale unui algoritm. De exemplu, s-ar putea s a denim algoritmi diferit i din punctul de vedere al raportului spat iu/timp. Strategiile pot folosite c and ace sti algoritmi sunt implementat i n ierarhii de clase. Un algoritm folose ste date de care client ii n-ar trebui s a stie. Se evit a expunerea de structuri complexe specice algoritmului. O clas a dene ste mai multe comportamente si acestea apar apelate n urma mai multor instruct iuni condit ionale complexe n interiorul operat iilor clasei. Fiecare ramur a a condit iilor este mutat a ntr-o clas a separat a.

19.3. STRUCTURA

119

19.3

Structur a

Figura 19.2: Structur a sablon Strategy Exist a dou a metode de transmitere a parametrilor c atre strategie: Se poate ca toate datele necesare algoritmului s a e transmise ca parametri atunci c and se apeleaz a acesta. Se poate ca atunci c and este apelat algoritmul s a i se transmit ao referint a la obiectul Context si obiectul strategie s a apeleze metode ale clasei Context pentru a obt ine datele necesare. Ca si modalitate de lucru, n general, se parcurg urm atorii pa si: 1. Se creeaz a obiectul Context 2. La creearea acestuia sau ulterior i se transmite de c atre client o strategie care va folosit a. Ulterior, clientul are posibilitatea, dac a dore ste s a schimbe strategia. 3. Clientul interact ioneaz a numai cu obiectul Context, acesta lucr and indirect cu obiectul strategie curent. Folosirea acestui sablon are mai multe consecint e (avantaje si dezavantaje): Este necesar a construirea unei ierarhii de clase cu algoritmi. Acest lucru poate bun deoarece ofer a un suport pentru factorizarea n clasa de baz a a comportamentului comun. Ofer a o alternativ a foarte buna la subclasare. S-ar putut s a deriv am direct clasa Context dar acest lucru nu ar fost a sa de bun din mai multe motive:

120

CAPITOLUL 19. STRATEGY Ar f acut mai greu de nt eles clasa Context. Nu ar permis varierea dinamic a a strategiei utilizate. Folosirea strategiilor elimin a instruct iunile condit ionale complexe. Permite alegerea foarte u soar a a implement arii dorite. Client ii sunt con stient i de diferitele strategii, ei ind responsabili cu actualizarea si stabilirea strategiei active. Uneori e greu de g asit o interfat a comun a ntre mai mult i algoritmi, n funct ie de complexitatea ec aruia. In aceste situat ii, uneori este necesar s a realiz am o leg atur a mult mai str ans a ntre context si strategie pentru a nu necesar s a transmitem parametri inutil. Strategiile pot cre ste foarte mult num arul de obiecte dintr-o aplicat ie, motiv pentru care uneori este mai bine ca ele s a e implementate sub forma unor obiecte f ar a stare care s a e partajate de toate obiectele din aplicat ie.

19.4

Exemplul 1

Problem a: S a se g aseasc a o metod a prin care s a putem sorta elementele unui sir cu obiecte de orice tip.
public interface Comparator <T> { int compare(T o1, T o2); } public class Arrays { public static <T> void sort(T[] a, Comparator<? super T> c) { for(int i=0;i<a.length-1;i++) for(int j=i+1;j<a.length;j++) if(c.compare(a[i], a[j])>0) { T aux=a[i]; a[i]=a[j]; a[j]=aux; } } }

19.5. EXEMPLUL 2

121

public class TestCompare { public static void main(String[] args) { String[] s={"Angela","Adriana","Viorel","Mariana","Cristian"}; Arrays.sort(s, new Comparator<String>() { public int compare(String s1, String s2) { return s1.compareToIgnoreCase(s2); } }); for(int i=0;i<s.length;i++) System.out.print(s[i]+" "); } }

19.5

Exemplul 2

Problem a: S a se implementeze acela si lucru folosind facilit a tile oferite de mediul Java si C#.

import java.util.Arrays; public class TestCompare { public static void main(String[] args) { String[] s={"Angela","Adriana","Viorel","Mariana","Cristian"}; Arrays.sort(s, new java.util.Comparator<String>() { public int compare(String s1, String s2) { return s1.compareToIgnoreCase(s2); } }); for(int i=0;i<s.length;i++) System.out.print(s[i]+" "); } }

Exemplul corespunz ator C#este prezentat n gura 19.3.

122

CAPITOLUL 19. STRATEGY

Figura 19.3: Utilizare Strategy in C#

19.6

Exemplul al 3-lea

Problem a: S a se implementeze un joc de X&0 folosind sablonul Strategy pentru stabilirea dicult a tii jocului.
public class TestGame { public static void main(String[] args) { X0Game game=new X0Game(); game.setLevel(GameLevel.EASY); //playing the game } } public interface GameLevel {

19.6. EXEMPLUL AL 3-LEA


void makeMove(int[][] a, int playerNo); final static GameLevel EASY=new GameLevel() { public void makeMove(int[][] a, int playerNo) { //TODO de implementat metoda makeMove } }; final static GameLevel MEDIUM=new GameLevel() { public void makeMove(int[][] a, int playerNo) { //TODO de implementat metoda makeMove } }; final static GameLevel DIFFICULT=new GameLevel() { public void makeMove(int[][] a, int playerNo) { //TODO de implementat metoda makeMove } }; } public class X0Game { private GameLevel level; private int[][] a; private int currentPlayer; public void setLevel(GameLevel level) { this.level=level; } public void makeComputerMove() { level.makeMove(a, currentPlayer); currentPlayer=3-currentPlayer; } //TODO other methods to write }

123

124

CAPITOLUL 19. STRATEGY

Capitolul 20

Observer
20.1 Scop si motivare

Scop: Dene ste o dependent a de la unul la mai mult i ntre obiecte astfel nc at atunci c and un obiect si schimb a starea, toate cele dependente de el s a e noticate si actualizate automat. Motivare: Programarea obiect orientat a conduce la crearea mai multor clase, ntre care exist a mai multe leg aturi. De multe ori, atunci c and cont inutul unui obiect se schimb a mai multe alte obiecte care depind de acel obiect, trebuie anunt ate. Acest lucru trebuie realizat, pe c at posibil, astfel nc at s a nu e cuplate foarte mult clasele. Un astfel de exemplu este un document Excel n care avem mai multe reprezent ari ale acelora si date. In momentul n care se modic a anumite date, automat toate reprezent arile trebuie actualizate. Un exemplu este prezentat n gura 20.1. In aceast a gur a exist a un subiect, care ret ine date, precum si mai mult i observatori care si schimb a reprezent arile dac a datele din subiect se modic a. Mai mult, num arul de observatori este nedenit, ceea ce nseamn a c a se pot ad auga oric and alt i observatori. Ca observat ie suplimentar a, trebuie remarcat c a observatorii pot de tipuri foarte variate, lucru care face si mai util acest sablon. Practic, ntr-o aplicat ie care folose ste acest sablon se nt ampl a urm atoarele operat ii: 125

126

CAPITOLUL 20. OBSERVER

Figura 20.1: Motivare utilitate Observer Este creat un anumit obiect de tip subiect. Sunt create obiectele observator care se nregistreaz a n lista de observatori a subiectului. In momentul n care subiectul se modic a, automat toate obiectele care au fost nregistrate sunt anunt ate. In plus, la orice moment, se poate s a se nregistreze noi obiecte care din acel moment vor anunt ate de modic ari ale subiectului, sau s a se dez nregistreze obiecte care nu vor mai anunt ate din acel moment. Evident, pentru a putea s a- si actualizeze starea, ecare observator ret ine o referint a la obiectul model.

20.2

Aplicare

Se folose ste acest sablon n una din urm atoarele situat ii: C and o abstract ie are dou a aspecte, unul dependent de altul. Incapsularea acestor aspecte n obiecte separate permite varierea si reutilizarea lor independent a.

20.3. STRUCTURA

127

C and o schimbare ntr-un obiect necesit a schimbarea altora si nu se stie c ate astfel de obiecte trebuie schimbate. C and un obiect ar trebui s a e capabil s a notice alte obiecte f ar a a putea face presupuneri despre cine sunt aceste obiecte. Cu alte cuvinte, vrem evitarea cupl arii puternice ntre obiecte.

20.3

Structur a

Figura 20.2: Structur a sablon Observer Folosirea acestui sablon are mai multe consecint e: Cuplarea ntre subiect si observator este una abstract a. Un subiect nu stie nici tipul concret al observatorilor, nici num arul acestora. Un astfel de design, poate facilita comunicarea ntre layere diferite f ar a a strica designul aplicat iei. Avem o comunicare de tip broadcast. Subiectul nu transmite mesaje personalizate ec arui obiect, ci transmite acela si mesaj tuturor, doar obiectele interesate trat and acel mesaj. Trebuie lucrat cu grija, deoarece n urma modic arilor asupra subiectului, se pot produce mai multe actualiz ari ale observatorilor dec at ne-am a stepta. Uneori, are sens s a transmitem un mesaj care s a si descrie modicarea care s-a produs, pentru a mai u sor de tratat de c atre observatori.

128

CAPITOLUL 20. OBSERVER Uneori, dac a putem avea mai multe obiecte observate de c atre un observator, este necesar s a putem s a stim si cine este obiectul care a trimis noticarea. O problem a interesant a este cine ar trebui s a stabileasc a c and se fac notic arile? Exista dou a solut ii: Se poate ca oric and se modic a ceva n starea subiectului, tot i observatorii s a e anunt at i. Aceast a modalitate prezint a un avantaj si un dezavantaj. Avantajul ar c a nu mai trebuie ca utilizatorul s a- si aduc a aminte automat s a apeleze o anumit a metod a. Dezavantajul ar c a, n acest fel, s-ar putea ca mai multe actualiz ari consecutive s a conduc a la notic ari n cascad a. Se poate ca nici o noticare s a nu se fac a p an a c and clientul nu cere acest lucru. Problema, n acest caz este c a se poate ca clientul s a uite s a apeleze acea metod a. Exist a dou a modele de subiect i: Cei care transmit foarte multe detalii legate de schimbarea de stare care s-a produs n interiorul lor (modelul push) Cei care nu transmit aproape nici o informat ie despre schimbarea care s-a produs (modelul pull). Se poate ca observatorii s a se nregistreze la un subiect si din punctul de vedere al aspectului de care sunt interesat i. Astfel se elimin a numeroase apeluri inutile.

20.4
20.4.1

Exemple
Exemplul 1

In unele limbaje ecare component a are o metod a special a CompName Click, n care se poate pune codul pe care vrem s a-l execut am atunci c and se d a click pe acea component a. Componenta r aspunde unui num ar x de evenimente care nu poate schimbat.

20.4. EXEMPLE

129

In alte limbaje, gen limbajul C, trebuie ca programatorul s a fac a foarte multe lucruri, inclusiv o structur a repetitiv a n care s a se tot verice dac a s-au produs noi evenimente. Mediul Java promoveaz a o solut ie intermediar a. Programatorul controleaz a modul n care evenimentele sunt transmise de la event source la listeners. In Java orice obiect poate listener. Acest model, event delegation model este un pic mai exibil fat a de modelele anterioare, dar necesit a, mai mult cod dec at modul de lucru ca n prima situat ie prezentat a. Este un mod de lucru n care o surs a de evenimente poate avea nregistrat i mai multi observatori si de asemenea, un observator poate legat la mai multe surse de evenimente, eventual chiar diferite. Informat ia despre eveniment este ncapsulat a ntr-un obiect event, derivat din java.util.EventObject. Atunci c and vrem s a ad aug am un nou listener, n Java scriem un cod de genul urm ator: eventSource.addEventListener(eventListenerObject); Un listener este de fapt un observator n aceast a situat ie, el trebuind s a implementeze o interfat a cum ar , de exemplu ActionListener. C and se execut a un click pe un buton, n interiorul lui se creeaz a un eveniment de tipul ActionEvent si se apeleaz a: listener.actionPerformed(event); Evident, putem avea oric a ti listeneri, de tipuri foarte variate.

20.4.2

Exemplul 2

In cele ce urmeaz a prezent am un mic exemplu concret de implementare a sablonului Observer.


import java.util.*; public class Subject { private ArrayList<Observer> observers; public Subject() { observers=new ArrayList<Observer>();

130
} public void attach(Observer o) { observers.add(o); } public void detach(Observer o) { observers.remove(o); } public void notifyAllObservers() { for(Observer o:observers) o.update(this); } } public interface Observer { void update(Subject s); } import java.util.*; public class Lista extends Subject { private ArrayList<String> persoane; public Lista() { persoane=new ArrayList<String>(); } public void adaugaPersoana(String s) { persoane.add(s); notifyAllObservers(); } public void stergePersoana(String s) { persoane.remove(s); notifyAllObservers(); } public String toString() { StringBuilder sb=new StringBuilder(); for(String s:persoane) sb.append(s).append(" "); return sb.toString(); } }

CAPITOLUL 20. OBSERVER

20.4. EXEMPLE

131

public class Observator implements Observer{ private String name; private Lista subject; public Observator(String name, Lista subject) { this.name=name; this.subject=subject; subject.attach(this); } public void update(Subject s) { System.out.println(name+": S-a schimbat continutul listei..."); System.out.println(name+": Noul continut: "+subject); System.out.println(); } } public class TestObserver { public static void main(String[] args) { Lista lista=new Lista(); Observator obs1=new Observator("OBS 1", lista); Observator obs2=new Observator("OBS 2", lista); lista.adaugaPersoana("Adi"); lista.adaugaPersoana("Marcel"); lista.detach(obs1); lista.stergePersoana("Adi"); } }

20.4.3

Exemplul 3

In cadrul platformei JDK exist a suport pentru implementarea acestui sablon. Modul de lucru cu clasa Observable precum si cu interfat a Observer, ambele din pachetul java.util este prezentat n cele ce urmeaz a.

import java.util.*; public class Lista extends Observable{ private ArrayList<String> persoane; public Lista() {

132
persoane=new ArrayList<String>(); } public void adaugaPersoana(String s) { persoane.add(s); setChanged(); notifyObservers(); } public void stergePersoana(String s) { persoane.remove(s); setChanged(); notifyObservers(); } public String toString() { StringBuilder sb=new StringBuilder(); for(String s:persoane) sb.append(s).append(" "); return sb.toString(); } } import java.util.Observable; import java.util.Observer;

CAPITOLUL 20. OBSERVER

public class Observator implements Observer{ private String name; private Lista subject; public Observator(String name, Lista subject) { this.name=name; this.subject=subject; subject.addObserver(this); } public void update(Observable obs, Object o) { System.out.println(name+": S-a schimbat continutul listei..."); System.out.println(name+": Noul continut: "+subject); System.out.println(); } } public class TestObserver { public static void main(String[] args) { Lista lista=new Lista();

20.4. EXEMPLE
Observator obs1=new Observator("OBS 1", lista); Observator obs2=new Observator("OBS 2", lista); lista.adaugaPersoana("Adi"); lista.adaugaPersoana("Marcel"); lista.deleteObserver(obs1); lista.stergePersoana("Adi"); } }

133

134

CAPITOLUL 20. OBSERVER

Capitolul 21

Mediator
21.1 Scop si motivare

Scop: Dene ste un obiect care ncapsuleaz a modul n care mai multe obiecte interact ioneaz a. Mediator promoveaz a cuplarea slab a prin evitarea faptului ca obiectele s a se refere unele la altele n mod explicit, permit and astfel varierea independent a a interact iunii lor. Motivare: Designul obiect orientat ncurajeaz a distribut ia sarcinilor de efectuat ntre obiecte. Astfel de design-uri pot duce uneori, n situat ii mai complexe la cazuri n care majoritatea obiectelor ret ine referint e la multe din celelalte obiecte. Problema care apare este c a acest lucru contrazice principiul care spune c a vrem s a favoriz am cuplarea slab a si coeziunea nalt a. In acest caz am avea o cuplare foarte puternic a ntre diversele componente. Un exemplu foarte sugestiv este cel din gura 21.1. Adeseori, putem avea de-a face cu ferestre care cont in mai multe controale ntre care dependent ele pot destul de puternice. Aceste dependent e se pot exprima sub forma unor constr angeri precum: Un anumit buton poate dezactivat atunci c and un anumit c amp e gol. Selectarea unei anumite opt iuni dintr-o list a poate conduce la schimbarea altor alegeri. Pe m asur a ce textul este introdus ntr-un control, se poate ca anumite butoane s a devin a active iar altele s a e sterse etc. 135

136

CAPITOLUL 21. MEDIATOR

Figura 21.1: Motivare utilitate Mediator Evident, dependent ele sunt foarte puternice si, n acela si timp este greu de f acut o fereastr a reutilizabil a. Solut ia problemei o constituie introducerea not iunii de mediator. Mediatorul este un obiect care face leg aturile ntre alte obiecte, permit and ca acestea s a nu e con stiente unele de altele si promov and astfel o cuplare slab a. Mediatorul ret ine referint e la obiecte si la r andul lor obiectele pot ret ine referint e la mediator. C and un control si schimb a starea, el anunt a mediatorul care la r andul lui face tot ceea ce trebuie f acut ca si consecint a a acelei operat ii.

21.2

Aplicare

Se folose ste acest sablon atunci c and: Mai multe obiecte comunic a ntr-un mod bine denit dar complex. Interdependent ele lor sunt nestructurate si greu de nt eles. Reutilizarea unui obiect este dicil a deoarece el utilizeaz a si comunic a cu multe alte obiecte. Un comportament care este distribuit ntre mai multe clase ar trebui s a e customizabil f ar a foarte multe subclas ari.

21.3. STRUCTURA

137

21.3

Structur a

Figura 21.2: Structur a sablon Mediator

Figura 21.3: Diagrama de obiecte pentru sablonul Mediator Folosirea sablonului Mediator are mai multe consecint e importante: Ajut a la limitarea subclas arii, n sensul n care dac a dorim ca s a se schimbe comportamentul putem subclasa doar mediatorul nu si celelalte clase.

138

CAPITOLUL 21. MEDIATOR Decupleaz a diversele obiecte promov and principiul cupl arii slabe si a coeziunii nalte. Schimb a mai multe relat ii many-to-many n relat ii one-to-many care sunt mult mai u sor de nt eles, ment inut si extins. Face modul n care obiectele interact ioneaz a un subiect aparte, pun and astfel accent separat pe conexiunile ntre obiecte. Centralizeaz a controlul n cadrul mediatorului. Acest lucru poate deveni un dezavantaj n anumite situat ii, mai ales atunci c and mediatorul devine foarte complex.

21.4

Exemplu

Prezent am n cele ce urmeaza un mini-sistem de facturare a cump ar aturilor ntr-un magazin.


public class ScreenDisplay { public void add(String text) { System.out.println("SCREEN_DISPLAY: "+text); } } public class Product { private long id; private String desc; private double price; public Product(long id, String desc, double price) { this.id=id; this.desc=desc; this.price=price; } public long getId() { return id; } public void setId(long id) { this.id = id; }

21.4. EXEMPLU

139

public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } } import java.util.Hashtable; public class Inventory { private Hashtable<Long, Product> list=new Hashtable<Long, Product>(); public void init() list.put(1L, new list.put(2L, new list.put(3L, new } { Product(1, "pasta de dinti", 20)); Product(2, "detergent", 40)); Product(3, "produs 3", 60));

public Product getProduct(long id) { return list.get(id); } } public interface ScannerListener { public void scanned(long id); } import java.util.ArrayList; public class Scanner { private ArrayList<ScannerListener> list=new ArrayList<ScannerListener>(); public void scan(long id) { for(ScannerListener listener:list) listener.scanned(id); }

140

CAPITOLUL 21. MEDIATOR

public void addScannerListener(ScannerListener listener) { list.add(listener); } public void removeScannerListener(ScannerListener listener) { list.remove(listener); } } import java.util.*; public class MyChecker implements ScannerListener{ private Scanner scanner; private ScreenDisplay screen; private Inventory inventory; private List<Product> productList=new ArrayList<Product>(); public MyChecker(Scanner scanner, ScreenDisplay screen, Inventory inventory) { this.scanner=scanner; scanner.addScannerListener(this); this.screen=screen; this.inventory=inventory; } public void beginNewTransaction() { productList.clear(); } public void endTransaction() { double total=0; for(Product p:productList) total+=p.getPrice(); screen.add(String.format("Total amount to pay: %10.2f RON", total)); } public void scanned(long id) { Product p=inventory.getProduct(id); productList.add(p); screen.add(String.format("%5d. %-20s %10.2f RON", p.getId(),p.getDesc(),p.getPrice())); } } public class TestChecker { public static void main(String[] args) { Scanner scanner=new Scanner();

21.4. EXEMPLU
Inventory inventory=new Inventory(); inventory.init(); ScreenDisplay sd=new ScreenDisplay(); MyChecker checker =new MyChecker(scanner, sd, inventory); checker.beginNewTransaction(); scanner.scan(1); scanner.scan(3); checker.endTransaction(); } }

141

142

CAPITOLUL 21. MEDIATOR

Capitolul 22

Memento
22.1 Scop si motivare

Scop: F ar a a nc alca ncapsularea, captureaz a si externalizeaz a starea intern a a unui obiect astfel nc at obiectul s a poat a restaurat la acea stare la un moment ulterior. Motivare: In aplicat iile pe care le creem, adesea vrem s a putem salva starea anumitor obiecte, n a sa fel nc at, eventual, s a putem ulterior s a readucem obiectele la acea stare. Dac a am salva starea unui obiect ntr-un obiect extern, n modul clasic, atunci am putea avea surpriza s a constat am faptul c a s-a nc alcat n mod agrant ncapsularea (dac a orice alt obiect ar avea acces la datele protejate ale obiectului a c arui stare s-a salvat). In anumite situat ii si alternativa salv arii n interiorul obiectului a st arii interne a lui poate dezavantajoas a, deoarece ar conduce la cre sterea complexit a tii acelui obiect. Acest sablon rezolv a tocmai aceast a problem a, dar dup a cum vom putea vedea n continuare, el se aplic a mai greu n anumite limbaje si mai u sor n altele.

22.2

Aplicare

Se folose ste acest sablon atunci c and: O imagine a st arii unui obiect (sau o port iune a lui) trebuie salvat a astfel nc at s a poat a restaurat a la acea starea mai t arziu si 143

144

CAPITOLUL 22. MEMENTO O interfat a direct a la obt inerea st arii ar expune detalii de implementare si ar sparge ncapsularea.

22.3

Structur a

Figura 22.1: Structur a sablon Memento Folosirea sablonului Memento are mai multe consecint e: Face n a sa fel nc at, chiar dac a vrem s a ret inem extern datele referitoare la starea unui anumit obiect la un moment dat, acele date s a nu e accesibile pentru oricine. Acest lucru ar nc alca grav ncapsularea. Simplic a mult obiectul Originator, n sensul n care el nu mai este nevoit s a implementeze un mecanism care s a-i ret in a starea. Mai mult dec at at at, l face responsabil pentru acest lucru pe client, f ar a a-i da ns a posibilitatea s a acceseze datele salvate. Dac a datele care trebuie ret inute au dimensiuni mari, uneori acest sablon se poate dovedi prea costisitor, eventual ind nevoie de noi abord ari. In anumite limbaje s-ar putea s a e dicil s a ne asigur am c a numai obiectul care genereaz a memento-ul poate accesa acest obiect. Un Memento are dou a interfet e: O interfat a care este accesibil a numai obiectului care a generat Mementoul. O interfat a care este accesibil a tuturor celorlalate obiecte.

22.4. EXEMPLU

145

In C++ acest lucru se poate face astfel: clasa Originator este o clas a prieten a a clasei Memento, n timp ce tot ceea ce tine de interfat a care trebuie s a e disponibil a Originator-ului este f acut privat. Dac a am dori s a scriem o aplicat ie care s a aib a suport pentru Undo, avem de ales ntre 2 solut ii: Putem folosi sablonul Command, prin denirea pentru ecare operat ie a c ate unui obiect, care s a aib a dou a metode execute() si undo(). In unele situat ii e mai greu s a refacem o anumit a operat ie. Se poate ca n astfel de cazuri s a e mult mai convenabil s a ret inem datele care au fost modicate, urm and ca la o operat ie de Undo, ele doar s a e restaurate.

22.4

Exemplu

package com.mihai.objects; public class Memento { private int state; public Memento(int state) { this.state=state; } protected int getState() { return state; } } package com.mihai.objects; import java.util.Hashtable; import java.util.Set; public class MementoTable { private Hashtable<String, Memento> mementoHashtable= new Hashtable<String, Memento>(); public void addMemento(String desc, Memento m) { mementoHashtable.put(desc, m); }

146

CAPITOLUL 22. MEMENTO

public Memento getMemento(String desc) { return mementoHashtable.get(desc); } public Set<String> getKeys() { return mementoHashtable.keySet(); } } package com.mihai.objects; public class Originator { public int nr; public Originator(int nr) { this.nr=nr; } public int getNr() { return nr; } public void setNr(int nr) { this.nr=nr; } public Memento getMemento() { return new Memento(nr); } public void setMemento(Memento m) { nr=m.getState(); } } package com.mihai.app; import com.mihai.objects.Memento; import com.mihai.objects.MementoTable; import com.mihai.objects.Originator;

public class TestMemento { public static void main(String[] args) { MementoTable table=new MementoTable();

22.4. EXEMPLU
Originator orig=new Originator(3); orig.setNr(2); Memento memento=orig.getMemento(); table.addMemento("mem1", memento); orig.setNr(4); System.out.println("Noua valoare: "+orig.getNr()); memento=orig.getMemento(); table.addMemento("mem2", memento); orig.setNr(8); System.out.println("Noua valoare: "+orig.getNr()); Memento toRestore=table.getMemento("mem1"); orig.setMemento(toRestore); System.out.println("Valoarea dupa restaurare: "+orig.getNr()); } }

147

148

CAPITOLUL 22. MEMENTO

Capitolul 23

Visitor
23.1 Scop si motivare

Scop: Reprezint a operat ia care trebuie efectuat a asupra elementelor unei structuri de obiecte. Visitor permite denirea de noi operat ii f ar aa schimba clasele elementelor asupra c arora opereaz a. Motivare: In [GoF] este prezentat a situat ia n care am dori s a construim un compilator, care dup a ce si construie ste un arbore abstract de sintax a, dore ste s a fac a numeroase operat ii asupra acestor noduri obt inute. Astfel de operat ii ar putea : vericarea tipurilor, optimizarea codului, vericarea faptului c a variabilele au asignate valori nainte de a folosite, realizarea unor anumite metrici ale programului, a s ari n diverse formate etc. Pentru ecare tip de nod, va trebui s a implement am operat ii care s a fac a toate aceste lucruri. Dezavantajul major este c a, oric and am dori s a introducem o nou a operat ie, ar trebui s a modic am interfat a tuturor claselor obiectelor din structur a. Acest lucru ar putea conduce inclusiv la necesitatea recompil arii claselor. Solut ia acestei probleme o constituie, crearea pentru ecare tip de operat ie posibil a a unui vizitator. Acesta este un obiect care implementeaz a o operat ie particular a si care stie cum s a trateze ecare tip de obiect n parte. Toate obiectele din structur a vor declara nc a de la nceput faptul c a ele au abilitatea de a primi un vizitator. 149

150

CAPITOLUL 23. VISITOR

23.2

Aplicare

Se folose ste acest sablon atunci c and: O structur a cont ine mai multe tipuri de obiecte cu diferite tipuri de interfet e si se dore ste efectuarea de operat ii asupra acestor obiecte, operat ii care depind de clasele lor concrete. Multe operat ii distincte si ne nrudite trebuie efectuate asupra obiectelor dintr-o structur a si nu se dore ste poluarea acestor clase cu aceste operat ii. Visitor permite p astrarea acestor operat ii mpreun a prin denirea lor ntr-o singur a clas a. Clasele care alc atuiesc structura de obiecte se schimb a rar, dar adesea vrem s a denim noi operat ii asupra structurii. Schimbarea claselor structurii de obiecte cere redenirea tuturor interfet elor la vizitatori. Dac a clasele ale c aror obiecte se g asesc n structur a se schimb a des, este mai bine s a nu folosim Visitor.

23.3

Structur a

Figura 23.1: Structur a sablon Visitor Folosirea acestui sablon are mai multe consecint e:

23.4. EXEMPLU

151

Oric and se poate deni o nou a operat ie la care nu ne-am g andit c and am proiectat clasele, f ar a a nevoie s a le modic am. Vizitatorul face ca ntr-o clas a s a nu avem numeroase operat ii ntre care s a nu existe leg aturi. Ad augarea unui nou element concret este dicil a n cazul sablonului Visitor, deoarece ar necesita ad augarea unei noi operat ii pentru Visitor, urmat de denirea acelei operat ii pentru ecare vizitator concret. Acesta este motivul pentru care se aplic a acest sablon mai ales atunci c and avem clase care prezint a o anumit a stabilitate. Un vizitator poate acumula stare pe m asur a ce viziteaz a obiectele din structur a. Vizitatorul porne ste de la premiza c a ecare element din structur a are o interfat a sucient de puternic a pentru ceea ce este necesar lui. Uneori, pentru ca vizitatorul s a- si poat a face treaba bine este necesar s a se sparg a ncapsularea.

23.4

Exemplu

public interface File { int getSize(); String getName(); void setHidden(boolean hidden); boolean isHidden(); } public interface Element { void accept(Visitor v); } public interface Visitor { void visit(Directory d); void visit(RegularFile f); } public class RegularFile implements File, Element{ private String name;

152
private int size; private boolean hidden;

CAPITOLUL 23. VISITOR

public RegularFile(String name, int size) { this.name=name; this.size=size; } public String getName() { return name; } public int getSize() { return size; } public void setHidden(boolean hidden) { this.hidden=hidden; } public boolean isHidden() { return hidden; } public void accept(Visitor v) { v.visit(this); } } import java.util.*; public class Directory implements Element, File{ private String name; private ArrayList<File> files; private boolean hidden; public Directory(String name) { this.name=name; files=new ArrayList<File>(); } public void addFile(File f) { files.add(f); } public void removeFile(File f) {

23.4. EXEMPLU
files.remove(f); } public int getSize() { int size=0; for(File f:files) size+=f.getSize(); return size; } public String getName() { return name; } public void setHidden(boolean hidden) { this.hidden=hidden; } public void accept(Visitor v) { v.visit(this); for(File f:files) f.accept(v); } } public class CountVisitor implements Visitor { private int files; private int directories; public void visit(Directory d) { directories++; } public void visit(RegularFile f) { files++; } public int getNumberOfFiles() { return files; } public int getNumberOfDirectories() { return directories; } }

153

154

CAPITOLUL 23. VISITOR

public class TestVisitor { public static void main(String[] args) { File f1=new RegularFile("primul", 10); File f2=new RegularFile("al doilea", 20); Directory d1=new Directory(d1); d1.addFile(f1); d1.addFile(f2); File f3=new RegularFile("al treilea", 30); Directory root=new Directory("root"); root.addFile(d1); root.addFile(f3); System.out.println("Dimensiunea direct radacina: "+root.getSize()); CountVisitor v=new CountVisitor(); root.accept(v); System.out.println("Numarul de directoare: "+v.getNumberOfDirectories()); System.out.println("Numarul de fisiere: "+v.getNumberOfFiles()); } }

Capitolul 24

Template
24.1 Scop si motivare

Scop: Dene ste scheletul unui algoritm ntr-o operat ie, las and anumit i pa si n sarcina subclaselor. Template Method las a subclasele s a redeneasc a anumit i pa si ai unui algoritm f ar a a schimba structura algoritmului. Motivare: S a presupunem c a avem un framework n care avem clasele Application si Document. Clasa Application se ocup a, printre altele, cu deschiderea documentelor n timp ce clasa Document reprezint a documentul propriu-zis. C and avem o aplicat ie particular a subclas am ecare din aceste subclase, pentru a rezolva problema respectiv a. Am putea avea ceva corespunz ator gurii 24.1. Cont inutul metodei openDocument() ar putea ar ata astfel: public void openDocument() { if(!canOpenDocument()) return; Document doc = doCreateDocument(); if(doc) { docs.addDocument(doc); aboutToOpenDocument(doc); doc.open(); doc.doRead(); } 155

156

CAPITOLUL 24. TEMPLATE

Figura 24.1: Motivare utilitate Template } In acest exemplu, openDocument() poart a numele de metod a template. Aceast a metod a dene ste un algoritm si ordinea n care se produc diversele operat ii, permit and ec arei subclase denirea anumitor operat ii.

24.2

Aplicare

Acest sablon de proiectare ar trebui utilizat: Pentru a implementa p art ile invariante ale unui algoritm si a l asa subclasele s a implementeze p art ile care variaz a. Atunci c and comportamentul comun ntre subclase ar trebui factorizat si localizat ntr-o clas a comun a pentru a evita duplicarea. Pentru a controla extensiile realizate cu ajutorul subclaselor. Se poate deni o metod a template care apeleaz a operat iile hook n anumite puncte specice, permit and extensia numai prin aceste puncte.

24.3

Structur a

Dup a cum se poate vedea ideea acestui sablon este de a avea o clas a de baz a n care unele metode sunt denite si altele nu. Metodele abs-

24.3. STRUCTURA

157

Figura 24.2: Structur a sablon Template tracte sunt folosite de celelalte metode, dup a care sunt denite ulterior n subclase. S ablonul reprezint a o tehnic a foarte util a pentru reutilizarea codului si este folosit cu prec adere n framework-uri. De multe ori, este o ilustrarea a principiului dont call us, well call you (principiul Hollywood), deoarece metodele din clasa de baz a le apeleaz a pe cele din clasa derivat a, nu invers. Metodele template pot apela mai multe tipuri de metode: operat ii concrete (posibil din subclase) operat ii concrete din clasa abstract a metode Factory hook operations - sunt metode care ofer a un comportament implicit pe care subclasele l pot extinde dac a este necesar. In general este important s a e specicate foarte clar care sunt operat iile care pot suprascrise si care sunt cele care trebuie specicate neap arat. Trebuie avute n vedere anumite lucruri care tin de implementare: In general, metodele care trebuie apelate pot declarate ca protected, ceea ce nseamn a c a ele pot apelate doar de metoda template ( si clasele din acela si pachet n Java).

158

CAPITOLUL 24. TEMPLATE Aproape ntotdeauna, metoda template este o metod a care nu poate suprascris a n subclase. Ea poate o metod a nevirtual a (nal a n Java si nevirtual a n C++). Cu c at num arul de metode care trebuie suprascrise este mai mic cu at at este mai bine, deoarece cel care va utiliza acea clas a o va utiliza cu mai mare u surint a.

24.4

Exemplu

public abstract class List { abstract public int count(); abstract public Object getElem(int i); abstract public void add(Object o); public boolean contains(Object o) { for(int i=0;i<count();i++) if(getElem(i).equals(o)) return true; return false; } public String toString() { StringBuilder s=new StringBuilder(); for(int i=0;i<count();i++) s.append(getElem(i)).append(" "); return s.toString(); } } public class ArrayList extends List { private Object[] data; private int count; public ArrayList(int dim) { data=new Object[dim]; } public int count() { return count; } public Object getElem(int i) { return data[i];

24.4. EXEMPLU
} public void add(Object o) { data[count++]=o; } } public class TestTemplate { public static void main(String args[]) { List list=new ArrayList(20); list.add("gigi"); list.add("marian"); System.out.println(list.contains("gigi")); System.out.println(list.getElem(0)); } }

159

160

CAPITOLUL 24. TEMPLATE

Capitolul 25

Concluzii
Se poate ca unii dintre voi s a ram an a cu ideea c a sabloanele de design nu sunt un lucru chiar at at de deosebit. La urma urmei, cei care au scris cartea nu le-au inventat, ci doar le-au catalogat, folosind idei existente. Mai mult dec at at at, p an a acum ceva vreme at i scris destule aplicat ii f ar a s a le folosit i n mod direct si lucrurile au funct ionat n bun a m asur a.

25.1
25.1.1

Ce s a a stept am de la sabloanele de design?


Un vocabular comun de design

De-a lungul timpului a devenit evident, n orice domeniu c a pentru a putea u sura comunicarea, este nevoie ca tot i cei implicat i ntr-un anumit proces s a foloseasc a termeni comuni (adesea termeni corespunz atori specializ arii). P an a de cur and f aceat i acela si lucru si n informatic a dar doar la nivel de algoritmi si structuri de date (folosim sortarea prin metoda quicksort, s a folosim o stiv a etc.). La nivel de design, comunicarea se f acea la nivel de not iuni primitive (clas a, metod a, etc.). Odat a cu nt elegerea sabloanelor de design comunicarea se poate face la un nivel mai nalt. In mod normal, ar trebui ca de-acum s a ncepet i s a folosit i expresii de genul:eu zic sa folosim aici un singleton, cel mai bine s-ar potrivi aici un abstract factory, etc. Dac a se va nt ampla a sa ceva, at i f acut un pas important nainte. 161

162

CAPITOLUL 25. CONCLUZII

25.1.2

Un ajutor pentru nv a tare si documentare

Cunoa sterea sabloanelor de design ajut a foarte mult la nt elegerea sistemelor soft obiect orientate existente. De multe ori suntem n situat ia de a trebui s a utiliz am un framework n care sunt folosite sabloane de proiectare. S abloanele de proiectare l fac pe cel care le cunoa ste un designer mai bun. Probabil, odat a cu trecerea timpului, oricum am putea nt elege singuri aceste solut ii dar cu ajutorul sabloanelor acest lucru se produce mult mai u sor si rapid. Descrierea unui sistem n termeni de sabloane de proiectare l face mult mai u sor de nt eles si permite o comunicat ie la un nivel mult mai nalt, ajut and foarte mult si la faza de documentare a sistemului (at at scrierea documentat iei, c at si alegerea unor denumiri c at mai semnicative). S abloanele de proiectare ofer a modalit a ti de folosire c at mai elegant a a not iunilor de baz a ale program arii obiect orientate: mo stenire, polimorsm, interfet e, clase abstracte etc. Sigur, odat a cu studierea lor, rolul acestor concepte a devenit mult mai evident. Acela si lucru s-ar putea spune si despre principalele idei legate de programarea obiect orientat a. Ele sunt respectate si exemplicate prin folosirea sabloanelor de design. folosirea compozit iei n dauna mo stenirii programarea pe interfet e si nu pe implement ari c and ceva variaz a acel lucru trebuie ncapsulat promovarea cupl arii slabe si a coeziunii nalte ncercarea de a realiza sisteme soft open-closed ... Permit introducerea de idei noi care s a sprijine procesul de refactoring. Practic, pentru cine studiaz a mai mult refactorizarea, devine evident faptul c a multe din metodele de refactorizare conduc direct sau indirect la designuri asem an atoare cu sabloanele de proiectare.

AS DE LA S 25.1. CE SA TEPTAM ABLOANELE DE DESIGN?

163

Mai mult dec at at at, designurile realizate folosind sabloane de proiectare sunt extensibile si exibile ceea ce reduce mult necesitatea refactoriz arii ulterioare.

S-ar putea să vă placă și