1. Ingineria programării
6. Șabloane de proiectare
creaționale (II)
Florin Leon
Universitatea Tehnică „Gheorghe Asachi” din Iași
Facultatea de Automatică și Calculatoare
http://florinleon.byethost24.com/curs_ip.htm
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
2. Șabloane de proiectare
creaționale (II)
1. Singleton
2. Prototip
3. Constructor
4. Concluzii
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
4. Notă
Programele care implementează șabloanele
descrise și care pot fi descărcate din pagina
cursului sunt parte integrantă a prezentării
4
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
5. Șabloane de proiectare
creaționale (II)
1. Singleton
2. Prototip
3. Constructor
4. Concluzii
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
6. 6
Singleton
Uneori este nevoie să garantăm faptul ca o clasă să aibă o
singură instanță
Bazin de resurse (engl. “resource pool”)
De exemplu: fire de execuție, conexiuni de rețea
Registrul Windows
Gestionarea unui set de preferințe
Interfață cu sistemul de operare
Driver pentru un dispozitiv
De exemplu: imprimantă, placă grafică, controller
Depozit de date (engl. “data repository”)
Un Singleton este o clasă care poate avea doar o singură
instanță
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
7. Definiție
Șablonul Singleton asigură faptul că o
clasă are doar o singură instanță și
furnizează un punct de acces global către
aceasta
7
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
9. 9
Alternative
Variabilă globală statică
Se alocă automat, chiar dacă nu va fi folosită
Clasă cu câmpuri statice
Spre deosebire de varianta statică, clasa Singleton este
o clasă normală, cu stare internă, metode de prelucrare
a acestei stări, se poate deriva sau poate implementa o
interfață
Inițializarea întârziată este utilă în cazul în care
obiectul folosește multe resurse
Instanța nu se alocă decât în momentul utilizării efective
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
12. 12
Multithreading
Două fire de execuție diferite pot accesa
secțiunea simultan și pot instanția două
obiecte
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
13. 13
Abordarea 2
secțiune sincronizată
toate citirile se fac după
blocare, iar toate scrierile se
fac înainte de deblocare
performațele scad datorită
blocării/deblocării la fiecare acces
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
15. 15
Modificatorul “volatile” utilizat
pentru un câmp accesat de mai
multe fire de execuție asigură
faptul că un fir de execuție citește
valoarea cea mai recentă a
câmpului, setată de un alt fir de
execuție.
Sistemul citește valoarea curentă
a unui obiect volatil în momentul
solicitării, chiar dacă instrucțiunea
precedentă a citit valoarea
aceluiași obiect. De asemenea,
valoarea obiectului este scrisă
imediat după atribuire.
Abordarea 3
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
16. 16
Abordarea 4
detalii în slide-ul următor
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
18. 18
Flag-ul beforefieldinit
Dacă flag-ul beforefieldinit este setat (adică atunci când
NU se definește un constructor static), CLR-ul instanțiază
clasa doar după ce are loc una din următoarele situații:
Se creează o instanță a clasei sau
Este accesat un câmp static sau o metodă statică a clasei
Înainte de a fi accesat un membru static, JIT verifică dacă a fost
apelat mai întâi constructorul static: scade performanța, dar crește
siguranța
CLR = Common Language Runtime (mediul de execuție pentru program)
JIT = Just-In-Time compiler
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
19. Constructorul static
În exemplul de mai jos, dacă flag-ul beforefieldinit este
setat, este posibil ca r1 să nu fie inițializat când se
apelează metodele Method1 și Method2, deoarece
metodele nu accesează câmpul r1
În general, se recomandă folosirea constructorului static,
pentru a evita defecte subtile, greu de depistat
19
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
20. 20
Dificultăți
Java
Classloader
Garbage collector
C++
Resursele folosite de un Singleton trebuie dezalocate la
închiderea aplicației
Singleton-ul Meyers definește instanța ca o variabilă locală
statică într-o funcție, care returnează o referință la ea
O astfel de definiție invocă destructorul Singleton înainte
de terminarea programului, prevenind scurgerile de
memorie (engl. “memory leaks”)
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
21. 21
Singleton în C++
GoF: instanța este creată când
se apelează prima dată
metoda, dar nu este distrusă
Meyers: instanța este creată la fel,
dar destructorul se apelează
înainte de terminarea programului
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
22. Dificultăți
Singleton-ul este o modalitate de lucru cu stări globale
Stările globale trebuie evitate pe cât posibil deoarece:
Pot fi modificate de orice parte din program, ceea ce face dificilă
înțelegerea tuturor utilizărilor posibile
Două apeluri identice pot avea rezultate diferite dacă stările
globale, utilizate de ambele, se modifică între timp
Sunt greu de testat:
Două componente care funcționează corect în izolare pot funcționa
incorect când sunt testate împreună
Poate fi nevoie simultan de mai multe cópii ale mediului de execuție,
de exemplu pentru a verifica unele proprietăți invariante
22
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
23. Injectarea dependențelor
Folosind stări globale, codul este mai greu de întreținut:
dependențele nu apar explicit
O soluție este injectarea dependențelor: în constructor,
într-o metodă setter sau într-o metodă normală
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
24. 24
Exemple C#
Cele 4 variante...
Structura...
Load Balancer...
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
28. 28
Discuție
Unele șabloane pot fi implementate folosind un
Singleton
De exemplu, o Fabrică abstractă poate utiliza un Singleton
pentru a asigura unicitatea fabricii
Fabricile trebuie să fie accesibile global; prin folosirea unui
Singleton, se asigură faptul că o singură fabrică va controla
crearea obiectelor
Această abordare este utilă dacă fabrica alocă instanțele
de obiecte dintr-un bazin (engl. “pool”) de obiecte
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
29. Șabloane de proiectare
creaționale (II)
1. Singleton
2. Prototip
3. Constructor
4. Concluzii
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
30. 30
Clonarea
O alternativă la instanțierea unei clase este
realizarea unei clone a unui obiect
O clonă este o copie a unui obiect
Clona are starea sursei la momentul creării
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
31. 31
Copii superficiale și profunde
engl. “shallow copies”, “deep copies”
La copierea obiectelor care au referințe la alte
entități (de exemplu, obiecte) se pune întrebarea:
trebuie copiate referințele sau entitățile referențiate?
Copie superficială: se copiază referințele
Copie profundă: se copiază entitățile referențiate și
orice alte entități referențiate recursiv
Tipul de copiere recomandat depinde de situație
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
32. 32
Copii superficiale și profunde
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
33. Definiție
Șablonul Prototip precizează, folosind o
instanță prototip, tipurile de obiecte ce vor
fi create și creează noile obiecte copiind
acest prototip
33
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
34. 34
Șablonul Prototip
Ideea de bază: utilizarea unei instanțe tipice pentru a
crea o instanță înrudită
Folosește clonarea, implementată de o metodă Clone()
Asemănător cu Metoda fabrică, dar se returnează un
obiect de același tip, nu un „Produs”
Utilizează interfețe pentru a decupla clientul de produsul
clonat
Nu specifică dacă clonarea este superficială sau
profundă. Tipul depinde de problema curentă
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
37. Exemplu: prototipuri grafice
Se poate construi un editor de note muzicale
particularizând un editor grafic general
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
38. 38
Template-urile Word
Template-urile sunt prototipuri de documente completate
parțial, care urmează să fie modificate de utilizator
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
39. Font-uri C#
textBox.Font = new Font(textBox.Font, newStyle);
39
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
40. Clonare în C#
Clonare superficială
Clonare profundă
40
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
41. Manager de prototipuri
Un manager de prototipuri este o clasă utilizată
pentru a adăuga și regăsi prototipuri într-o
manieră centralizată, pe baza unor parametri, de
exemplu indecși numere întregi sau enumerări
41
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
42. 42
Exemple C#
Structura...
Color Manager...
Swimmers...
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
46. 46
Aplicabilitate
Când clienții trebuie decuplați de produse:
Dacă clasele care trebuie instanțiate sunt specificate în
momentul execuției (de exemplu, încărcare dinamică)
Pentru a evita construirea unei ierarhii de fabrici paralele
cu ierarhia de produse
Dacă instanțele unei clase pot avea una sau doar câteva
combinații distincte de stări
Prototipul este asemănător cu Metoda fabrică, însă
folosește clonarea în loc de instanțiere
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
47. 47
Dificultăți
Se poate dori inițializarea unor valori după clonare
Problema principală este legată de tipul clonării
Clonarea superficială poate afecta datele partajate
În cazul unei clone profunde, toate componentele clonei
trebuie să fie clone ale componentelor prototipurilor
Clonarea profundă este imposibilă în cazul referințelor
circulare
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
48. Șabloane de proiectare
creaționale (II)
1. Singleton
2. Prototip
3. Constructor
4. Concluzii
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
49. 49
Constructor
Șablonul Constructor separă construcția unui
obiect complex de reprezentarea acestuia, astfel
încât același proces de construcție să poată
crea reprezentări diferite
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
55. Variante
Același director poate folosi mai mulți
constructori concreți pentru a crea diferite
produse concrete
Ca în exemplele prezentate anterior
Aceeași interfață de constructor poate fi folosită
de mai mulți directori
Ca în exemplul următor
55
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
57. 57
Aplicabilitate
Când algoritmul de creare a unui obiect complex
este independent de părțile care compun
obiectul și de modul lor de asamblare
Când procesul de construcție trebuie să permită
reprezentări diferite pentru obiectul construit
Șablonul este des folosit în realizarea parserelor
pentru diferite formate
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
58. 58
Discuție
Constructorul creează un obiect complex pas cu pas.
Fabrica abstractă creează familii de obiecte, câte un
component odată
Produsul este returnat de Constructor ca ultim pas,
Fabrica abstractă returnează un produs imediat
Constructorul încapsulează logica modului în care este
asamblat un obiect complex, astfel încât clientul poate
doar să ceară o configurație, iar directorul direcționează
logica de construire
Fabrica abstractă este preocupată de CE se realizează,
Constructorul este preocupat de CUM se realizează
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
59. 59
Discuție
Deseori, proiectarea poate să înceapă cu Metoda fabrică
(mai simplă) și să evolueze către alte șabloane mai
flexibile și mai complexe (Prototip, Constructor, Fabrica
abstractă)
Constructorul poate utiliza alte șabloane pentru a
implementa componentele care se construiesc
Constructorul, Fabrica abstractă și Prototipul pot utiliza un
Singleton pentru implementare
Constructorul construiește deseori o Compunere
(engl. “Composite”, șablon structural)
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
60. 60
Șabloane înrudite
Prototip Fabrica
abstractă
Constructor
Un obiect folosit pentru a crea
alte obiecte-produs specifice
Obiectul fabrică
produse din mai
multe clase
Un produs complex
este construit
incremental
Produsul este creat
prin copierea și
modificarea unui
obiect prototip
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
61. 61
Concluzii
Șablonul Singleton garantează că dintr-o clasă
poate exista numai o singură instanță
Șablonul Prototip are ca scop clonarea
instanțelor de obiecte în momentul execuției pe
baza unor obiecte prototip
Șablonul Constructor abstractizează pașii de
construire a unui obiect astfel încât diferite
implementări ale acestor pași pot construi
reprezentări diferite ale obiectelor
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm