CATEGORII DOCUMENTE |
Sabloane de proiectare
Toate sistemele orientate pe obiecte bine structurate abunda in sabloane (patterns), mergand de la mecanisme care contureaza forma sistemului in ansamblu, pana la sabloane locale (cum ar fi de exemplu modul de tratare a exceptiilor).
Un sablon reprezinta o solutie comuna a unei probleme intr-un anumit context.
Importanta sabloanelor (standardelor) in construirea sistemelor complexe a fost de mult recunoscuta in alte discipline. In cadrul comunitatii proiectantilor de software OO ideea de a aplica sabloane se pare ca a fost inspirata de propunerea unui arhitect, Christopher Alexander, care a lansat initiativa folosirii unui limbaj bazat pe sabloane pentru proiectarea cladirilor si a oraselor. Acesta afirma ca: 'Fiecare sablon descrie o problema care apare mereu in domeniul nostru de activitate si indica esenta solutiei acelei probleme, intr-un mod care permite utilizarea solutiei de nenumarate ori in contexte diferite'.
Desi in domeniul sistemelor OO solutiile sunt exprimate in termeni de obiecte si interfete (in loc de ziduri, usi, grinzi etc), esenta notiunii de sablon este aceeasi, adica de solutie a unei probleme intr-un context dat.
Majoritatea sistemelor OO includ mecanisme referitoare la:
persistenta obiectelor
controlul stocarii
controlul proceselor
transmisia/receptia mesajelor
distribuirea si migrarea obiectelor
conectarea in retele (networking)
tranzactii
evenimente
modul de prezentare ('look & feel') al aplicatiei.
Proiectarea sistemelor OO este o activitate dificila, iar proiectarea sistemelor OO reutilizabile este inca si mai grea. Solutia trebuie sa fie specifica problemei, dar totodata suficient de generala pentru a putea fi aplicata si pe viitor, pentru a evita in ultima instanta 'reinventarea rotii' de fiecare data (sau cel putin pentru a minimiza acest lucru).
Un proiectant fara experienta este de multe ori coplesit de multitudinea optiunilor disponibile si are tendinta de a se intoarce la tehnicile non-obiectuale pe care le-a folosit in trecut. Un proiectant experimentat stie ca NU TREBUIE sa rezolve fiecare problema incepand de la zero, ci reutilizand solutii din proiecte anterioare. Atunci cand descopera o solutie buna o va folosi mereu. Acest tip de experienta este o parte din ceea ce confera unui proiectant statutul de expert.
In cadrul sistemelor OO realizate in mod profesionist se pot distinge sabloane de clase si de obiecte in comunicare care rezolva probleme specifice si fac ca sistemele respective sa fie mai flexibile, mai elegante si reutilizabile. Un proiectant familiar cu asemnea sabloane le va putea aplica repede, fara a trebui sa le redescopere.
Sabloanele de proiectare sunt de fapt o memorare pentru posteritate a experientei in domeniul proiectarii sistemelor OO.
Criterii de clasificare:
v dupa scop: sabloanele pot fi creationale, structurale sau comportamentale.
v dupa domeniul de aplicare: sabloanele se pot aplica obiectelor sau claselor.
Sabloanele creationale ale obiectelor acopera situatiile in care o parte din procesul crearii unui obiect cade in sarcina unui alt obiect.
Sabloanele structurale ale obiectelor descriu caile prin care se asambleaza obiecte.
Sabloanele comportamentale ale obiectelor descriu modul in care un grup de obiecte coopereaza pentru a indeplini o sarcina ce nu ar putea fi efectuata de un singur obiect.
Sabloanele creationale ale claselor acopera situatiile in care o parte din procesul crearii unui obiect cade in sarcina subclaselor.
Sabloanele structurale ale claselor descriu modul de utilizare a mostenirii in scopul compunerii claselor.
Sabloanele comportamentale ale claselor utilizeaza mostenirea pentru descrierea unor algoritmi si fluxuri de control.
Sabloane creationale |
|
Furnizeaza o interfata pentru crearea unor familii de obiecte |
|
Separa obiectele construite de reprezentarea lor |
|
Creaza o instanta a diferitelor clase derivate |
|
O instanta initializata poate fi copiata sau clonata |
|
O clasa din care doar o singura instanta poate exista |
|
Sabloane structurale |
|
Face ca interfetele diferitelor clase sa corespunda |
|
Separa interfata unui obiect de implementarea acestuia |
|
Structura arborescenta de obiecte simple si compuse |
|
Adauga responsabilitati obiectelor in mod dinamic |
|
O singura clasa ce reprezinta un intreg sistem |
|
O instanta folosita pentru un sharing eficient |
|
Un obiect reprezentand un un alt obiect |
Behavioral Patterns |
|
O cale de a transmite cereri intre obiecte |
|
Incapsuleaza o cerere ca un obiect |
|
O cale de a include elemente lingvistice intr-un program |
|
Acces secvential la elementele unei colectii |
|
Defineste comunicarea simplificata intre clase |
|
Capteaza si reconstitui starea interna a unui obiect |
|
O cale de a anunta schimbarea unui numar de clase |
|
Modificarea comportamentului unui obiect atunci cand isi schimba starea |
|
Incapsuleaza un algoritm intr-o clasa |
|
Transfera pasii exacti ai unui algoritm unei subclase |
|
Defineste o noua operatie pentru o clasa fara a face schimbari |
Abstract Factory Pattern - sablon creational de obiect
Sablonul furnizeaza o interfata pentru crearea unor familii de obiecte inrudite sau dependente intre ele, fara a specifica clasa lor concreta. Se mai numeste si kit
Frecventa in utilizare: medie-mare
Sa luam de exemplu cazul unui generator de interfete grafice utilizator (GUI) care ofera suport pentru standarde multiple privind modul de prezentare a elementelor interfetei. Diferitele moduri de prezentare ('look & feel') definesc diferite stiluri si modalitati de comportare ale elementelor de control (bare de defilare, ferestre, butoane, meniuri etc). Pentru a asigura portabilitatea intre diferitele standarde, o aplicatie nu trebuie sa fixeze prin cod un anumit tip de elemente de control. Instantierea, in intreaga aplicatie, a unor clase specifice unui standard de prezentare si aspect face dificila modificarea ulterioara a prezentarii si aspectului. Problema se poate rezolva prin definirea unei clase abstracte care declara o interfata pentru crearea fiecarui element de control GUI. Pentru fiecare element de control va exista cate o clasa abstracta care il modeleaza precum si mai multe clase concrete, corespunzatoare diverselor standarde de prezentare. Interfata are cate o operatie care returneaza un nou obiect din fiecare clasa abstracta ce modeleaza un element de control. Clientii vor apela aceste operatii pentru a obtine instante ale elementelor de control, fara sa le 'pese' de standardul de prezentare, deci fara a sti la ce clase concrete apartin acele instante.
Sablonul Abstract Factory se utilizeaza cand:
v un sistem trebuie sa fie independent de modul in care produsele sale sunt create, compuse si reprezentate;
v un sistem trebuie sa fie configurat la un moment dat cu una din mai multe familii de produse;
v trebuie impusa restrictia ca produsele dintr-o anumita familie sa fie utilizate impreuna si nu amestecate cu produsele altei familii;
v se doreste crearea unei biblioteci de produse pentru care sunt relevante doar interfetele, nu si implementarile (de exemplu, in cazul unui generator de interfete, nu ne intereseaza cum sunt desenate pe ecran diversele elemente de control, ci doar care sunt efectele actionarii lor de catre utilizator si aceste efecte sunt asemanatoare, indiferent de standardul de prezentare).
In figura de mai jos este data structura de clase care constituie sablonul Abstract Factory:
AbstractFactory - declara o interfata pentru operatii de creare a produselor abstracte;
ConcreteFactory - implementeaza operatiile de creare a produselor concrete;
AbstractProduct - declara o interfata pentru o categorie de produse;
ConcreteProduct
o defineste un produs care va fi creat de un obiect ConcreteFactory corespunzator;
o implementeaza interfata AbstractProduct
Client - utilizeaza doar interfetele AbstractFactory si AbstractProduct
In mod normal, la executie se creaza cate o singura
instanta a claselor ConcreteFactory. Aceste instante vor crea
produse avand o implementare particulara. Pentru a obtine produse diferite,
clientii trebuie sa utilizeze alte clase ConcreteFactory. Clasa AbstractFactory
paseaza sarcina crearii produselor spre subclasele ei ConcreteFactory.
Consecinte
P Izolarea claselor concrete: deoarece o clasa producator (factory) incapsuleaza responsabilitatea si procesul crearii obiectelor-produs, ea izoleaza clientii fata de clasele de implementare. Clientii manipuleaza instantele doar prin intermediul interfetelor lor abstracte. Numele claselor care modeleaza produsele apar doar in implementarile producatorilor concreti (ConcreteFactory)., nu si in codul clientului.
P Inlocuirea familiilor de produse: deoarece un producator concret apare intr-un singur loc intr-o aplicatie, si anume acolo unde este instantiat, este usor ca el sa fie schimbat la un moment dat. Intrucat un producator abstract creaza o familie completa de produse, schimbarea se aplica la intreaga familie.
P Pastrarea consistentei produselor: sablonul AbstractFactory, prin structura sa, forteaza o aplicatie sa lucreaza cu obiectele dintr-o singura familie la un moment dat.
P Dezavantaj: extinderea unui producator abstract, in vederea crearii de produse noi in cadrul aceleiasi familii nu este simpla, deoarece implica modificarea tuturor subclaselor lui AbstractFactory.
O aplicatie necesita de regula cate o singura instanta a clasei ConcreteFactory per familie de produse. De aceea, este bine ca aceste clase sa fie implementate ca Singleton
Clasa AbstractFactory declara doar o interfata pentru a crea produsele. Cade in sarcina claselor ConcreteProduct crearea propriu-zisa. Aici cel mai bine se poate aplica sablonul FactoryMethod pentru fiecare produs din familie.
Extinderea producatorilor: asa cum s-a aratat mai sus, operatia de modificare a unui producator pentru a-l determina sa creeze noi produse nu este simpla. Ceea ce se poate face in acest sens este ca, in loc de a avea cate o operatie de forma CreateProduct pentru fiecare produs in parte, sa se definesca o singura operatie Create care sa primeasca un parametru de identificare a tipului de produs dorit. Aceasta varianta este flexibila, dar mai putin sigura. Problema care se ridica aici este aceea ca toate instantele returnate de operatia Create vor avea aceeasi interfata, si anume cea corespunzatoare tipului returnat de Create, iar clientul nu va putea determina intotdeauna care este clasa reala de care apartine instanta obtinuta.
Exemplu de implementare a sablonului Abstract Factory
package AbstractFactory;
// 'AbstractFactory'
public abstract class LocatieBursaFactory
class BursaLondra extends LocatieBursaFactory
}
public class BursaNewYork extends LocatieBursaFactory
// 'AbstractProductA'
abstract class Actiune
public class IBM1 extends Actiune
public IBM1(double ppret, String plocatie)
}
public class IBM2 extends Actiune
public IBM2(double ppret, String plocatie)
}
// 'Client'
public class Investitor
public void compar(Actiune a1, Actiune a2)
public class Comparatie
public static void main(String[] args)
}
Composite Pattern - sablon structural de obiect
Sablonul Composite realizeaza compunerea obiectelor intr-o structura de arbore, pentru a reprezenta ierarhii de tipul 'intreg-parti componente'. Da clientilor posibilitatea de a trata in mod uniform atat obiectele individuale, cat si structurile compuse de obiecte.
Frecventa in utilizare: mare
Aplicatiile de genul editoarelor
grafice permit utilizatorilor sa construiasca diagrame complexe pe baza unor
componente simple. Componentele pot fi grupate pentru a forma structuri
compuse, care la randul lor pot fi grupate pentru a forma structuri mai mari
s.a.m.d.
Intr-o aplicatie grafica simpla putem considera ca elemente primitive obiecte
ca: Text, Linie si Dreptunghi. Pe
langa acestea, vor fi definite alte clase, cu rol de containere pentru
elementele primitive. Problema care se pune aici este aceea ca, atat obiectele
primitive, cat si containerele sa poata fi tratate uniform de catre clienti.
Sablonul Composite aplica principiul compunerii recursive pentru
a rezolva aceasta problema.
Elementul cheie al sablonului Composite il constituie definirea unei clase abstracte care sa reprezinte atat primitivele, cat si containerele. Pentru exemplul nostru, o asemenea clasa este Grafic, a carei interfata include:
operatia Draw, specifica tuturor obiectelor ca modeleaza elemente grafice;
operatii specifice containerelor, adica operatii de acces si gestionare a elementelor componente (Add, Remove, GetChild):
Clasele Linie, Dreptunghi
si Text, care reprezinta elemente grafice primitive, vor
implementa operatia Draw pentru a desena linii, dreptunghiuri si
respectiv text. Aceste clase nu vor include celelalte operatii din grafic,
deoarece ele nu au elemente componente (children).
Clasa Imagine defineste un agregat de obiecte Grafic.
operatia Imagine::Draw este implementata ca o secventa de apeluri
ale operatiilor Draw pentru obiectele Grafic
componente.
In figura de mai jos este reprezentata o posibila structura pentru un container de tip Imagine:
Deoarece Imagine este un container, ea va include si operatiile specifice containerelor, deci interfata ei este aceeasi cu cea a clasei Grafic. Urmarea este ca un element al containerului Imagine poate fi, la randul sau, un al container. Acest mod de a combina obiectele in structuri ierarhice se numeste compunere recursiva.
Sablonul Composite se aplica in situatiile in care:
v se doreste reprezentarea unor ierarhii de obiecte de tipul 'intreg-element component'
v se urmareste sa se dea clientilor posibilitatea de a trata uniform obiectele individuale si agregatele de obiecte.
In figura de mai jos este data structura de clase care constituie sablonul Composite:
Component
o declara interfata pentru obiectele ce vor forma ierarhia;
o ofera o implementare implicita, comuna tuturor claselor, pentru operatiile interfetei;
o declara o interfata pentru accesul si gestionarea obiectelor care compun un container;
o optional, defineste o interfata pentru accesul la obiectul container dinspre elementele componente.
Leaf
o reprezinta obiecte elementare ale ierarhiei; un obiect Leaf nu are in componenta sa alte obiecte;
o defineste comportamentul specific unui obiect primitiv.
Composite
o defineste comportamentul obiectelor de tip container;
o implementeaza operatiile din Component privitoare la componentele containerului.
Client manipuleaza obiectele ierarhiei utilizand interfata Component.
Obiectele Client
utilizeaza interfata Component pentru a interactiona cu obiectele
dintr-o structura compusa. Daca obiectul receptor este un Leaf,
mesajul este tratat direct. Daca receptorul este un Composite,
atunci el va redirectiona mesajul spre fiecare din componentele sale. Este
posibil ca inainte si/sau dupa redirectionare sa se execute si alte operatii
aditionale.
Sablonul Composite:
P permite ca un client sa trateze uniform obiectele Leaf si Composite, fara a avea nevoie sa stie exact cu ce obiect concret lucreaza la un moment dat;
P da posibilitatea ca adaugarea unor noi clase Leaf sau Composite sa nu afecteze clasele client;
P are dezavantajul ca nu ofera un mecanism prin care sa se poata impune anumite restrictii, inca la compilare, asupra tipului elementelor care pot face parte dintr-un container; pentru aceasta este nevoie sa se faca verificari in timpul executiei.
Pastrarea de referinte dinspre componente spre containerul din care fac parte poate usura traversarea ierarhiei de obiecte, respectiv operatia de stergere a componentelor. Locul cel mai indicat pentru referinta spre container este clasa Component, de unde va putea fi mostenita de Leaf si Composite. In cazul in care se memoreaza aceasta referinta, este important sa se asigure consistenta informatiei, adica sa nu apara situatii in care un element indica spre un alt container decat cel care il contine. In acest scop, cel mai simplu este ca modificarea referintei spre container sa se faca doar in cadrul operatiilor Add/Remove din Composite, ceea ce asigura automat conditia de consistenta.
Unul din scopurile sablonului Composite este, asa cum s-a aratat mai sus, acela de a permite clientilor sa lucreze cu obiectele Leaf si Composite in mod uniform, clasa concreta de care apartin obiectele respective fiind transparenta. Pentru aceasta, clasa Component trebuie sa defineasca cat mai multe dintre operatiile ce pot sa apara in Leaf si Composite. De obicei, Component ofera implementari implicite la aceste operatii, urmand ca Leaf si Composite sa le redefineasca.
Exemplu de implementare a sablonului Composite
package Composite;
abstract class Angajat
// Methods
abstract public void AddSubordonat( Angajat a );
abstract public void RemoveSubordonat( Angajat a);
abstract public void getSubordonati(int indent);
}
// 'Composite'
public class Manager extends Angajat
// Methods
public void AddSubordonat(Angajat c )
public void RemoveSubordonat(Angajat c )
public void getSubordonati(int indent)
}
}
// 'Leaf'
public class PostSimplu extends Angajat
// Methods
public void AddSubordonat(Angajat b)
public void RemoveSubordonat( Angajat b )
public void getSubordonati(int indent)
public class Organigrama
public static void main(String[] args)
Observer Pattern - sablon comportamental de obiect
Sablonul defineste o dependenta "unul la mai multi " intre obiecte, astfel incat in cazul in care un obiect isi schimba starea, vor fi instiintate si actualizate automat toate obiectele sale dependente.
Frecventa de utilizare mare
In cazul partitionarii unui sistem intr-o colectie de clase cooperante este nevoia de pastrare a consistentei intre obiecte inrudite. Nu se doreste obtinerea consistentei prin cuplarea stransa a claselor, deoarece acest lucru reduce posibilitatea de reutilizare a lor. De exemplu, multe seturi de instrumente pentru interfete grafice cu utilizatorul de datele de baza ale aplicatiei. Clasele care definesc datele aplicatiei si cele care definesc prezentarile pot fi reutilizate independent, dar pot si sa lucreze impreuna. Atat un obiect foaie de calcul tabelar, cat si un obiect diagrama cu bare pot ilustra informatia provenita din aceleasi date de aplicatie, folosind insa prezentari diferite. Foaia de calcul tabelar si diagrama de bare nu stiu una despre cealalta, permitand astfel reutilizarea doar a celei care este necesara, insa se comporta ca si cum ar sti. Cand utilizatorul modifica informatia din foaia de calcul tabelar, diagrama cu bare reflecta imediat modificarile si viceversa.
Acest comportament implica faptul ca foaia de calcul tabelar si diagrama cu bare depind de un obiect cu date si, prin urmare, trebuie sa fie instiintate de orice modificare a starii acesteia din urma. Numarul de obiecte dependente poate depasi 2, la aceleasi date pot exista oricate interfete cu utilizatorul.
Obiectele cheie din acest sablon sunt subiectul si observatorul. Un subiect poate avea orice numar de observatori dependenti. Toti observatorii sunt instiintati ori de cate ori subiectul suporta o modificare a starii. Fiecare observator va interoga subiectul pentru a-si sincroniza starea cu starea subiectului.
Sablonul Observer se utilizeaza:
v Cand o abstractizare are doua aspecte, unul depinzand de celalalt. Incapsularea acestor aspecte in obiecte separate permite varierea si reutilizarea lor independente.
v Cand modificarea unui obiect necesita modificarea altor obiecte si nu se stie cat de multe obiecte trebuie schimbate
v Cand un obiect trebuie sa poata instiinta alte obiecte fara a fi obligat sa faca presupuneri despre identitatea acestora.
In figura de mai jos este data structura de clase care constituie sablonul Composite:
Subject
o Isi cunoaste observatorii. Un subiect poate fi observat de oricat de multe obiecte Observer
o Furnizeaza o interfata pentru atasarea si detasarea obiectelor Observer
Observer
o Defineste o interfata de actualizare pentru obiectele care trebuie sa fie instiintate de modificarile dintr-un subiect.
ConcreteSubject
o Stocheaza starile ce prezinta interes pentru obiectele ConcreteObserver;
o Cand i se modifica starea, trimite instiintari catre observatorii sai.
ConcreteObserver
o Pastreaza o referinta catre un obiect ConcreteSubject.
o Stocheaza starea, care trebuie sa fie consecventa cu cea a subiectului.
o Implementeaza interfata de actualizare Observer pentru a-si pastra starea in concordanta cu cea a subiectului.
Clasa ConcreteSubject isi instiinteaza observatorii ori de cate ori apare o modificare care ar putea face ca starea observatorilor sa nu mai concorde cu starea sa proprie. Dupa ce a fost informat de o modificare in subiectul concret, un obiect ConcreteObserver poate interoga subiectul pentru a obtine informatii. Obiectul ConcreteObserver utilizeaza aceste informatii pentru a reconcilia starea sa cu cea a subiectului.
Prin intermediul sablonului Observer se pot refolosi subiectii fara a refolosi observatorii si viceversa. Sablonul permite adaugarea de noi observatori fara a modifica subiectul sau alti observatori.
Avantaje si dezavantaje:
v Cuplarea abstracta intre subiect si observator. Subiectul are o lista de observatori, dar nu cunoaste clasa concreta a nici unuia dintre ei.
v Suport pentru comunicatii pe scara larga. Instiintarea trimisa de un subiect nu trebuie sa isi precizeze destinatarul, ea fiind trimisa tuturor observatorilor. Subiectului nu ii pasa cat de multe obiecte interesate exista, singura lui responsabilitate fiind aceea de a-si instiinta observatorii.
v Actualizari neasteptate. Deoarece observatorii nu au stiinta unul de prezenta celuilalt, ei s-ar putea sa nu sesizeze costul final al modificarii subiectului. De asemenea, criteriile de dependenta care nu sunt bine definite sau intretinute pot duce la actualizari false care pot fi dificil de depistat.
Exemplu de implementare a sablonului Observer
package ObserverPattern;
import java.util.ArrayList;
public abstract class Actiune
// Methods
public void Attach(IInvestor investor)
public void Detach(IInvestor investor)
public void Notify()
// Properties
public double getPret()
public void setPret(double value)
public class IBM extends Actiune
// 'Observer'
interface IInvestor
// 'ConcreteObserver'
public class Investor implements IInvestor
// Methods
public void update( Actiune s )
// Properties
public Actiune getActiune()
public void setActiune(double value)
public class ObserverAp
public static void main(String[] args)
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 5486
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved