ALTE DOCUMENTE
|
||||
Factory Method
Alte nume: Virtual Constructor
Proprietati
Tip: Creational
Nivel: Clasa
Scop
Defineste o metoda standard de creare a unui obiect, alta decât constructorul clasei acestuia. Decizia privitoare la ce fel de obiect se creeaza este lasata (delegata) la subclasele sale.
Introducere. Exemplu de problema: PIM (Personal Information Manager) 313b111d
PIM gestioneaza multe tipuri (elemente) de informatie: persoane, adrese, întâlniri, date, carti citite etc. Informatia nu este statica: trebuie sa se poata modifica adresa când o persoana se muta sau sa se poata modifica detaliile unei întâlniri când prânzul se mai târziu cu o ora.
PIM raspunde de modificarea fiecarui câmp, prin urmare el raspunde atât de editare în interfata cu utilizatorul, cât si de validarea informatiei introduse. Marele dezavantaj este ca PIM trebuie sa tina cont de particularitatile fiecarui element de informatie pe care o gestioneaza. Fiecare element de informatie are câmpuri specifice - utilizatorul trebuie sa aiba în fata o fereastra de editare cu câmpurile respective. Ori de câte ori trebuie inclus în PIM un element de informatie nou, codul sursa al PIM trebuie modificat pentru a include noile caracteristici de editare. Similar, daca un element de informatie existent se modifica (i se adauga un nou câmp, de exemplu), PIM trebuie modificat corespunzator. Dupa câteva astfel de operatii, codul PIM devine greu de înteles si de gestionat.
Solutia este sa se delege sarcina editarii si validarii la elementele de informatie. PIM trebuie doar sa stie cum sa ceara un editor, apelând metoda getEditor, care este implementata de orice element de informatie. Metoda va întoarce un obiect care implementeaza interfata ItemEditor, iar PIM va folosi obiectul pentru a cere un obiect JComponent pe post de editor GUI. Folosind acest editor, specific elementului de informatie, utilizatorul poate vedea câmpurile specifice si le poate modifica. Toata informatia despre actualizarea unui element de informatie specific este continuta în editor, care este furnizat chiar de elementul de informatie respectiv.
Reprezentarea grafica a editorului este creata de el însusi.
Cu aceasta solutie, PIM poate gestiona un numar nedefinit de elemente de informatie fara ca sa se intervina în codul sau.
Aplicabilitate
sablonul Metoda Fabrica se foloseste când:
se doreste crearea unui cadru (framework) flexibil. Flexibilitatea se obtine prin amânarea luarii unor decizii (ca de exemplu ce tip de obiect se creeaza) pentru mai târziu
se doreste ca o subclasa sa decida ce tip de obiect se creeaza (si nu superclasele sale)
se stie când trebuie sa se creeze un obiect, dar nu se cunoaste ce fel de obiect trebuie creat
este nevoie de mai multi constructori cu aceeasi lista de parametri, lucru nepermis în Java. În locul acestora se folosesc metode Factory cu nume diferite.
Descriere
sablonul se numeste metoda Fabrica deoarece el creeaza (fabrica) obiecte la cerere. La începutul dezvoltarii unei aplicatii nu este clar ce fel de obiecte se vor folosi. De obicei avem doar o idee generala despre operatiile pe care trebuie sa le aiba obiectele respective, fara ca sa stim foarte mult despre implementarea acestora, care va fi facuta mai târziu fara a influenta prezentul.
Flexibilitatea descrisa se poate obtine prin folosirea interfetelor pentru obiectele respective. Apare însa o problema de programare: dintr-o interfata nu se pot crea obiecte. Pentru a crea obiecte se poate proceda astfel:
se creeaza o clasa concreta (ConcreteProduct) care sa implementeze interfata (Product) (clasic)
se extrage functionalitatea constructorului clasei ConcreteProduct de mai sus si se pune într-o metoda, metoda Factory. Aceasta produce un obiect ConcreteCreator, a carui singura responsabilitate este sa creeze obiecte adecvate, adica instante ale unei clase concrete (ConcreteProduct) ce implementeaza interfata (Product
Implementare
Figura 1. Diagrama de clase pentru sablonul Factory Method
Pentru a implementa sablonul metoda Factory, avem nevoie de urmatoarele:
Product - Interfata tuturor obiectelor create de fabrica.
ConcreteProduct - Clasa ce implementeaza interfata Product; nu are nevoie de constructor deoarece obiectele sale sunt create de ConcreteCreator
Creator - Interfata ce defineste metoda (metodele) Factory factoryMethod . Aceasta metoda returneaza un obiect ce implementeaza interfata Product
ConcreteCreator - Clasa care implementeaza interfata Creator, furnizând implementarea pentru factoryMethod
Avantaje si dezavantaje
Avantaje:
Solutia pentru PIM este foarte generica. PIM trebuie sa stie doar cum sa ceara un obiect editor pentru un element specific de informatie. Cunostintele despre cum se editeaza respectivul element de informatie sunt continute în editorul asociat acestuia, care poate, de asemenea, sa creeze interfata grafica pentru editare.
Solutia pentru PIM este modulara, permitând adaugarea de elemente de informatie noi sau modificarea celor existente fara a fi afectat codul PIM.
JDBC (Java DataBase Connectivity) foloseste sablonul metoda Fabrica în multe dintre interfetele sale. Se pot folosi diverse drivere JDBC, cu singura conditie ca oricare din ele sa implementeze interfata dorita; restul aplicatiei nu este afectat.
Dezavantaje:
Ori de câte ori apare un element de informatie (Product) nou, trebuie adaugata o clasa ce-l implementeaza (ConcreteProduct) si o clasa ce implementeaza metoda Fabrica corespunzatoare acestuia (ConcreteCreator
Variatiuni la acest sablon
Creator poate furniza o implementare standard a metodei Factory. În acest caz, Creator nu trebuie sa fie clasa abstracta sau interfata, ci poate fi clasa concreta. Avantajul este ca nu este nevoie sa se creeze clase derivate din ea.
Product se poate implementa sub forma de clasa abstracta. Deoarece Product este clasa, se pot pune în ea implementari ale altor metode.
Metoda Factory poate avea un parametru, pe baza caruia sa se decida ce tip de obiect Product se creeaza. Aceasta descreste numarul de clase metoda Fabrica necesare.
sabloane înrudite
Abstract Factory - Poate folosi una sau mai multe metode Factory.
Prototype - Previne crearea de clase ce implementeaza Creator
Template Method - Metodele Template apeleaza de obicei metode Factory.
Data Access Object - sablonul Data Access Object foloseste metoda Factory pentru a putea crea instante specifice de Data Access Objects fara a cunoaste care este baza de date concreta cu care se lucreaza.
Exemplu
Exemplul foloseste sablonul metoda Factory pentru a produce un editor pentru PIM. Interfetele sunt folosite pentru a îmbunatati flexibilitatea generala a sistemului.
Interfata Editable defineste o metoda builder (constructor), getEditor, care returneaza o interfata ItemEditor. Avantajul este ca orice element de informatie poate furniza propriul sau editor, care implementeaza interfata ItemEditor si care stie ce câmpuri se editeaza si ce reguli de validare se aplica. Singurul lucru care trebuie sa-l faca interfata cu utilizatorul este sa foloseasca interfata Editable pentru a obtine editorul adecvat.
Exemplul 1. Editable.java
1. public interface Editable
Interfata ItemEditor furnizeaza doua metode: getGUI si commitChanges. Metoda getGUI este o metoda Factory - ea returneaza un obiect JComponent care furnizeaza o GUI Swing pentru editarea elementului de informatie curent. Aceasta ofera flexibilitate sistemului: la adaugarea unui nou tip de element de informatie, interfata cu utilizatorul poate ramâne aceeasi, deoarece ea foloseste doar interfetele Editable si ItemEditor
Obiectul JComponent returnat de metoda getGUI poate avea tot ceea ce este necesar pentru a edita elementul de informatie în PIM. Interfata cu utilizatorul va folosi obiectul JComponent obtinut în fereastra sa de editare si-i va utiliza functionalitatea pentru a afisa si modifica câmpurile acestuia. Deoarece nu este nevoie numai de interfete grafice, ar fi o idee buna sa se includa o metoda getUI care sa returneze o interfata la Object sau alta interfata non-grafica.
A doua metoda, commitChanges, permite interfetei cu utilizatorul sa-i comunice editorului ca utilizatorul vrea sa finalizeze modificarile pe care le-a facut.
Exemplul 2. ItemEditor.java
1. import javax.swing.JComponent;
2. public interface ItemEditor
Codul din exemplul 3 ilustreaza implementarea unui element de informatie gestionat de PIM, Contact. Clasa Contact are doua atribute: numele persoanei si relatia acesteia cu utilizatorul. Aceste atribute sunt un exemplu de câmpuri pentru un element de informatie gestionat de PIM.
Exemplul 3. Contact.java
1. import java.awt.GridLayout;
2. import java.io.Serializable;
3. import javax.swing.JComponent;
4. import javax.swing.JLabel;
5. import javax.swing.JPanel;
6. import javax.swing.JTextField;
8. public class Contact implements Editable, Serializable
private class ContactEditor implements ItemEditor, Serializable else
return panel;
}
public void commitChanges()
}
public String toString()
}
Contact implementeaza interfata Editable si furnizeaza propriul sau editor. Acest editor este folosit numai de clasa Contact, si are ca scop afisarea si modificarea atributelor acestei clase. Din acest motiv, este (cel mai) bine sa fie implementat sub forma unei clase interioare a clasei Contact. Clasa interioara (inner) are acces direct la atributele clasei exterioare (outer). Daca editorul n-ar fi fost clasa interioara a lui Contact , aceasta ar fi avut nevoie de metode accesor si mutator pentru fiecare din atributele sale, facând dificila restrângerea accesului la datele private ale obiectului.
Sa observam ca editorul nu este o componenta Swing, ci doar un obiect care are rol de fabrica pentru o astfel de componenta. Beneficiul esential este acela ca acest obiect se poate serializa si trimite într-un stream. Pentru a implementa aceasta, toate atributele care sunt componente Swing din ContactEditor se declara transient - ele se construiesc doar atunci si acolo unde este nevoie de ele.
|