poodlucanu/cursuri/poo/resurse/... · 2009. 4. 27. · d. lucanu poo –proiectarea de clase 11...
TRANSCRIPT
POO
Sabloane de proiectare
Fabrica de obiecte
D. Lucanu POO – Proiectarea de clase 2
Cuprins
sabloane de proiectare (software design patterns)
• fabrica de obiecte (Abstract Object Factory)
Fabrica de obiecte (Abstract Factory)
intentie
• de a furniza o interfata pentru crearea unei familii de
obiecte intercorelate sau dependente fara a specifica
clasa lor concreta
aplicabilitate
• un sistem ar trebui sa fie independent de modul in
care sunt create produsele, compuse sau
reprezentate
• un sistem ar urma sa fie configurat cu familii multiple
de produse
• o familie de obiecte intercorelate este proiectata
pentru astfel ca obiectele sa fie utilizate impreuna
• vrei sa furniziei o biblioteca de produse ai vrei sa
accesibila numai interfata, nu si implementarea
D. Lucanu POO – Proiectarea de clase 3
D. Lucanu POO – Proiectarea de clase 4
Fabrica de obiecte:: motivatie
typedef enum {SEGMID = 1, CERCID} TipFig;
citeste()
Figura
citeste()
Segment
citeste()
Cerc
incarca()
ContainerFig
1 *
D. Lucanu POO – Proiectarea de clase 5
Fabrica de obiecte:: motivatie
void ContainerFig::incarca(std::ifstream& inp){
while (inp){
// citeste tipul figuriiint tipFig; inp >> tipFig;// creeaza un obiect vidFigura* pfig;switch (tipFig){case SEGMID:
pfig = new Segment;break;
case CERCID:pfig = new Cerc;break; //...
}pfig->citeste(inp);
}}
Fabrica de obiecte:: structura
D. Lucanu POO – Proiectarea de clase 6
Fabrica de obiecte (diagrama din GoF)
D. Lucanu POO – Proiectarea de clase 7
Fabrica de obiecte
colaborari
• normal se creeaza o singura instanta
Consecinte
• izoleaza clasele concrete
• simplifica schimbul familiei de produse
• promoveaza consistenta printre produse
• suporta noi timpul noi familii de produse usor
• respecta principiul deschis/inchis
implementare
D. Lucanu POO – Proiectarea de clase 8
D. Lucanu POO – Proiectarea de clase 9
Functii delegat (callback)
o functie delegat (callback) este o functie care nu este
invocata explicit de programator; responsabilitatea
apelarii este delegata altei functii care primeste ca
parametru adresa functiei delegat
Fabrica de obiecte utilizeaza functii delegat pentru
crearea de obiecte: pentru fiecare tip este delegata
functia carea creeaza obiecte de acel tip
D. Lucanu POO – Proiectarea de clase 10
Fabrica de obiecte:: solutia
definim mai intai clasa de baza ca si clasa abstracta
class CFigure
{
public:
virtual void print() const = 0;
virtual void save( ofstream& outFile )
const = 0;
virtual void load( ifstream& inFile ) = 0;
};
D. Lucanu POO – Proiectarea de clase 11
Fabrica de obiecte:: solutia
definim apoi o fabrica de figuri, adica o clasa care sa
gestioneze tipurile de figuri
• inregistreaza un nou tip de figura (apelata ori de cate
ori se defineste o noua clasa derivata)
• eliminarea unui tip de figura inregistrat (stergerea unei
clase derivate)
• crearea de figuri
la nivel de implementare utilizam perechi
(IdTipFig, PointerFunctieDeCreareDelegata)
D. Lucanu POO – Proiectarea de clase 12
CAbstractFigFactory
class CAbstractFigFactory
{
public:
typedef CFigure* ( *CreateFigureCallback )();
bool RegisterFigure( int figureId,
CreateFigureCallback CreateFn );
bool UnregisterFigure( int figureId );
CFigure* CreateFigure( int figureId );
private:
typedef map<int, CreateFigureCallback>
CallbackMap;
CallbackMap callbacks_;
};
D. Lucanu POO – Proiectarea de clase 13
CAbstractFigFactory ::RegisterFigure()
bool
CAbstractFigFactory::RegisterFigure
( int figureId,
CreateFigureCallback CreateFn )
{
return
callbacks_.insert( CallbackMap::value_type
( figureId, CreateFn )
).second;
}
CAbstractFigFactory::UnregisterFigure()
bool
CAbstractFigFactory::UnregisterFigure
( int figureId )
{
return
callbacks_.erase( figureId ) == 1;
}
D. Lucanu POO – Proiectarea de clase 14
CAbstractFigFactory::CreateFigure()
CFigure*
CAbstractFigFactory::CreateFigure
( int figureId )
{
CallbackMap::const_iterator
i = callbacks_.find( figureId );
if ( i == callbacks_.end() )
throw string( "Unknown figure ID" );
return (i->second)();
}
D. Lucanu POO – Proiectarea de clase 15
D. Lucanu POO – Proiectarea de clase 16
CFigFactory
class CFigFactory : public CAbstractFigFactory
{
public:
static CFigFactory* getInstance()
{
if ( pInstance == 0 )
pInstance = new CFigFactory();
return pInstance;
}
private:
CFigFactory() { }
static CFigFactory* pInstance;
};
D. Lucanu POO – Proiectarea de clase 17
CContainer
class CContainer
{CContainer
public:
CContainer();
void save( ofstream& outFile ) const;
void load( ifstream& inFile );
void add( CFigure* _pF );
void print() const;
private:
vector<CFigure*> figures;
// vector of pointers to figures
};
CContainer::load()
void CContainer::load( ifstream& inFile )
{
int figureType;
while ( inFile >> figureType )
{
CFigure* pNewFigure;
pNewFigure = CFigFactory::getInstance()->
CreateFigure( figureType );
pNewFigure->load( inFile );
add( pNewFigure );
}
}
D. Lucanu POO – Proiectarea de clase 18
CContainer::save()
void CContainer::save( ofstream& outFile )
const
{
for ( unsigned int i = 0;
i < figures.size();
i++
)
figures[i]->save( outFile );
}
D. Lucanu POO – Proiectarea de clase 19
D. Lucanu POO – Proiectarea de clase 20
Fabrica de obiecte:: un nou tip de figura
class CCircle: public CFigure
{
public:
CCircle();
void print() const;
void save( ofstream& outFile ) const;
void load( ifstream& inFile );
private:
double x, y, r;
};
D. Lucanu POO – Proiectarea de clase 21
Fabrica de obiecte:: inregistrarea unui nou tip
namespace
{
CFigure* CreateCircle()
{
return new CCircle;
}
const int CIRCLE = 1;
const bool registeredCircle =
CFigFactory::getInstance()->
RegisterFigure( CIRCLE, CreateCircle );
}
D. Lucanu POO – Proiectarea de clase 22
Fabrica de obiecte::demo
int main()
{
try
{
ifstream f_in( "in.txt" );
ofstream f_out( "out.txt" );
CContainer tower;
tower.load( f_in );
tower.save( f_out );
}
catch (char* msg)
{
std::cout << msg;
}
}
Codul din GoF
D. Lucanu POO – Proiectarea de clase 23