ALTE DOCUMENTE
|
||||
Abstract Factory
Alte nume: Kit, Toolkit
Pattern Properties
Tip: Creational, Obiect
Nivel: Componenta
Scop
Furnizeaza un contract pentru crearea familiilor de obiecte dependente înrudite fara a fi nevoie de specificarea claselor concrete.
Introducere. Exemplu de problema: PIM (Personal Information Manager)
Sa consideram ca avem nevoie de gestiunea adreselor si numerelor de telefon, ca parte a unei aplicatii PIM (Personal Information Manager). PIM va functiona ca o combinatie între o carte de adrese, un planificator personal & 414o149e #351;i un gestionar de întâlniri si contacte, utilizând extensiv datele privitoare la adrese si la numerele de telefon.
Clasele care reprezinta datele de adresa si numere de telefon, numite în continuare Address si PhoneNumber, se pot produce de la început. La proiectarea lor se vor stabili câmpurile necesare (pentru a înmagazina toata informatia relevanta) si formatul de introducere si afisare a acestora. De exemplu, toate numerele de telefon din America de Nord au 10 cifre, iar codul postal trebuie sa fie într-un format specific.
La putin timp dupa codificarea claselor respective, se descopera ca trebuie gestionate adrese si numere de telefon dintr-o tara europeana, de exemplu Olanda. Pentru Olanda exista alte reguli privitoare la numerele de telefon si la codul postal, prin urmare codul introdus în clasele Address si PhoneNumber trebuie modificat pentru a satisface si cerintele Olandei.
Povestea de mai sus se poate repeta cu orice alta tara ce are reguli specifice pivitoare la formatul de afisare a numarului de telefon si al adresei. Pe masura ce se include cod pentru alt format, clasele de baza Address si PhoneNumber devin din ce în ce mai greu de gestionat si de înteles. Orice modificare a codului necesita apoi recompilarea claselor modificate.
O solutie mai buna ar fi sa se adauge flexibil perechi de astfel de clase, specifice fiecarei tari; sa se gaseasca regulile generale care se aplica la formatarea adreselor si numerelor de telefon si sa se permita "încarcarea" în sistem a oricarui alt format specific unei anumite tari.
sablonul Abstract Factory (Fabrica Abstracta) rezolva aceasta problema. Folosindu-l, se defineste AddressFactory - un cadru generic pentru producerea de obiecte care respecta sablonul general de formatare pentru clasele Address si PhoneNumber. La executie, fabrica este "dotata" cu un numar arbitrar de fabrici concrete, fiecare specifica unei anumite tari; fiecare tara are versiunile sale specifice pentru clasele Address si PhoneNumber
În locul cosmarului provocat de adaugarea de functionalitate noua la clasele existente, clasele de baza Address si PhoneNumber se vor extinde: Address la DutchAddress si the PhoneNumber la DutchPhoneNumber; instantele claselor derivate vor fi create de fabrica
DutchAddressFactory. Aceasta abordare ofera o mare libertate de extindere a codului fara a implica modificari structurale majore în restul sistemului.
Aplicabilitate
sablonul Abstract Factory se foloseste când:
Clientul trebuie sa fie independent de modul în care se creeaza produsele.
Aplicatia trebuie configurata cu una sau mai multe familii de produse.
Obiectele care trebuie create trebuie sa fie compatibile între ele.
Se doreste furnizarea unei colectii de clase pentru care se publica numai contractele si relatiile dintre ele, nu si implementarile acestora.
Descriere
Exista situatii când o aplicatie are nevoie sa foloseasca o varietate de resurse sau medii de operare. Exemplele uzuale de resurse includ:
Ferestrele (interfata grafica a unei aplicatii)
Sistemele de gestiune a fisierelor
Comunicarea cu alte aplicatii sau sisteme
În aceste tipuri de aplicatii se doreste o suficient de mare flexibilitate, cu scopul de a folosi o varietate din aceste resurse fara a fi nevoie de modificarea codului aplicatiei ori de câte ori se introduce o noua resursa.
O modalitate eficienta de rezolvare a acestei probleme este definirea unui creator generic de resurse, Fabrica Abstracta (Abstract Factory). Fabrica va avea una sau mai multe metode create care se pot apela pentru a produce resurse generice sau produse abstracte.
Java ("Java technology") se executa pe mai multe platforme, fiecare cu implementari foarte diferite ale resurselor de genul sistemelor de gestiune a fisierelor sau ferestrelor. Solutia adoptata de Java a fost abstractizarea conceptelor de fisier si fereastra si ascunderea implementarilor concrete ale acestora. Aplicatia se poate dezvolta folosind caracteristicile generice ale resurselor ca si cum acestea ar reprezenta functionalitate reala.
În timpul executiei, se creeaza obiecte din clasele ConcreteFactory si ConcreteProduct care sunt apoi utilizate de aplicatie. Clasele concrete respecta contractele definite de clasele AbstractFactory si AbstractProducts, prin urmare ele se pot utiliza direct, fara a avea nevoie sa fie înregistrate sau sa necesite recompilarea clientului.
Implementare
Diagrama de clase Abstract Factory este prezentata în Figura 1.1
Pentru a implementa sablonul metoda Factory, avem nevoie de urmatoarele:
AbstractFactory - Clasa abstracta sau interfata care defineste metodele create pentru produse abstracte.
AbstractProduct - Clasa abstracta sau interfata care defineste comportamentul general al resursei ce va fi folosita de aplicatie.
ConcreteFactory - Clasa derivata din fabrica abstracta. Ea implementeaza metodele create pentru unul sau mai multe produse concrete.
ConcreteProduct - Clasa derivata din produsul abstract, ce furnizeaza implementarea pentru resursa specifica sau mediul de operare specific.
Figura 1.1. Diagrama de clase a sablonului Abstract Factory
Avantaje si dezavantaje
Avantaje:
O Abstract Factory ajuta la cresterea flexibilitatii generale a unei aplicatii. Aceasta flexibilitate se manifesta atât la proiectare, cât si la executie. La proiectare, nu este nevoie sa se prevada (cunoasca) toate posibilele utilizari ale unei aplicatii.
Se creeaza în schimb un cadru generic si apoi se dezvolta implementari independente de restul aplicatiei. La executie, aplicatia poate sa integreze usor noi caracteristici si resurse.
Un alt beneficiu al acestui sablon este acela ca se simplifica testarea restului aplicatiei. Implementarea claselor de test TestConcreteFactory si TestConcreteProduct este simpla; ea poate simula comportamentul asteptat al resursei.
Dezavantaje:
Pentru a profita de avantajele expuse, trebuie definita cu atentie interfata generica pentru produsul abstract. Daca produsul abstract este impropriu definit, producerea unora dintre produsele concrete dorite poate fi foarte dificila si chiar imposibila.
Variatiuni la acest sablon
Cum s-a amintit mai sus, AbstractFactory si AbstractProduct se pot defini ca interfete sau clase abstracte, în functie de necesitatile aplicatiei sau preferintele Dvs.
În functie de modul cum va fi folosita fabrica, unele variante ale acestui sablon permit producerea de obiecte ConcreteFactory multiple, rezultând o aplicatie care poate folosi simultan familii multiple de ConcreteProducts
sabloane înrudite
Factory Method - Se foloseste la implementarea sablonului Abstract Factory.
Singleton - Folosit frecvent în Concrete Factory.
Data Access Object [CJ2EEP] - sablonul Data Access Object poate folosi sablonul Abstract Factory pentru a se obtine flexibilitate în crearea de fabrici specifice diverselor obiecte Database.
Observatie - [CJ2EEP] refera sabloanele J2EE, puse în bibliografie
Exemplu
Codul urmator ilustreaza modul în care folosirea sablonului Abstract Factory în PIM usureaza gestionarea formatelor (inter)nationale de adrese si numere de telefon. Interfata AddressFactory reprezinta fabrica:
Exemplul 1. AddressFactory.java
1. public interface AddressFactory
Sa observam ca AddressFactory defineste doua metode fabrica, createAddress si createPhoneNumber Acestea produc produsele abstracte Address si PhoneNumber, care definesc metodele pe care produsele le suporta.
Exemplul 2 Address.java
1. public abstract class Address
12. public String getCity()
13. public String getPostalCode()
14. public String getRegion()
15. public abstract String getCountry();
17. public String getFullAddress()
22. public void setStreet(String newStreet)
23. public void setCity(String newCity)
24. public void setRegion(String newRegion)
25. public void setPostalCode(String newPostalCode)
Exemplul 3 PhoneNumber.java
1. public abstract class PhoneNumber
public void setPhoneNumber(String newNumber)
catch (NumberFormatException exc)
}
Address si PhoneNumber sunt clase abstracte în acest exemplu, dar se pot usor defini ca interfete daca nu aveti nevoie de a defini cod general pentru toate produsele.
Pentru a furniza functionalitate concreta sistemului, trebuie sa se creeze clasele Concrete Factory si Concrete Product. Pentru fiecare tara se defineste o clasa care implementeaza interfata AddressFactory si doua clase derivate din Address si PhoneNumber. Urmatoarele trei clase ilustreaza acest lucru pentru SUA.
Exemplul 4 USAddressFactory.java
1. public class USAddressFactory implements AddressFactory
public PhoneNumber createPhoneNumber()
Exemplul 5 USAddress.java
1. public class USAddress extends Address
public String getFullAddress()
Exemplul 6 USPhoneNumber.java
1. public class USPhoneNumber extends PhoneNumber
public void setPhoneNumber(String newNumber)
}
Cadrul generic din AddressFactory Address, and PhoneNumber face usoara extinderea sistemului pentru alte tari. Pentru fiecare tara se defineste o clasa specifica ConcreteFactory si clase Concrete Product corespunzatoare. În continuare sunt prezentate clasele pentru Franta.
Exemplul 7 FrenchAddressFactory.java
1. public class FrenchAddressFactory implements AddressFactory
6. public PhoneNumber createPhoneNumber()
Exemplul 8 FrenchAddress.java
1. public class FrenchAddress extends Address
public String getFullAddress()
Exemplul 9 FrenchPhoneNumber.java
1. public class FrenchPhoneNumber extends PhoneNumber
public void setPhoneNumber(String newNumber)
|