Producatorul abstract (Abstract Factory)
Definitie
Ofera o interfata pentru crearea unor familii de obiecte
inrudite sau dependente intre ele, fara a specifica clasa lor concreta.
Se mai numeste si kit.
Context
Consideram un generator de interfete grafice utilizator
(GUI) care ofera suport pentru standarde multiple privind modul de prezentare
a elementelor interfetei. Exemple de asemenea standarde sunt: Motif, Presentation
Manager (PM) etc. 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.
Problema se poate rezolva prin definirea unei clase abstracte,
pe care o vom numi WidgetFactory si 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 (de exemplu:
Window, ScrollBar) precum si mai multe clase
concrete, corespunzatoare diverselor standarde de prezentare. Interfata
WidgetFactory 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:
Motivatii
Sablonul Abstract Factory se utilizeaza cand:
un sistem trebuie sa fie independent de modul in care produsele sale sunt create, compuse si reprezentate;
un sistem trebuie sa fie configurat la un moment dat cu una din mai multe familii de produse;
trebuie fortata restrictia ca produsele dintr-o anumita familie sa fie utilizate impreuna si nu amestecate cu produsele altei familii;
se doreste crearea unei biblioteci de produse pentru care sunt relevante doar interfetele, nu si implementarile (de exemplu, in cazul generatorului de interfete analizat mai inainte, 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 asemenatoare, indiferent de standardul de prezentare).
Solutie
In figura de mai jos este data structura de clase care constituie sablonul Abstract Factory:
Consecinte
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. De exemplu, clientul lucreaza doar cu instante ale clasei Window, nu cu PMWindow sau MotifWindow.Implementare
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.
Pastrarea consistentei produselor: sablonul AbstractFactory, prin structura sa, forteaza o aplicatie sa lucreaza cu obiectele dintr-o singura familie la un moment dat.
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 (vezi exemplul de la Factory Method). 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.
Tema
Sa se scrie un program care aplica sablonul Abstract Factory pentru urmatoarea structura de clase:
Lista ASCII:Listele in varianta HTML vor fi create in fisiere HTML, cu ajutorul tag-urilor <ul> si <li>.
*element_lista_1
*element_lista_2
*etc