Documente Academic
Documente Profesional
Documente Cultură
Sabloane
comportamentale
Cuprins
l
l
l
Visitor
Observer
Iterator
D. Lucanu
POO
Sablonul
Visitor
(prezentare bazata pe GoF)
Intentie
l
D. Lucanu
Motivatie
l
D. Lucanu
Solutie necorespunzatoare
l
D. Lucanu
Solutia cu vizitatori
D. Lucanu
Aplicabilitate
l
D. Lucanu
Structura
D. Lucanu
Participanti 1/2
l
Visitor (NodeVisitor)
declara cate o operatie de vizitare pentru fiecare clasa
ConcreteElement din structura. Numele operatiei si
signatura identifica clasa care trimite cererea de
vizitare catre vizitator. Aceasta permite vizitatorului sa
identifice elementul concret pe care il viziteaza. Apoi,
vizitatorul poate vizita elementul prin intermediul
interfetei sale.
ConcreteVisitor (TypeCheckingVisitor)
implementeaza fiecare operatie declarata de vizitator.
Fiecare operatie implementeaza un fragment din
algoritmul de vizitare care corespunde elementului din
structura vizitat. Memoreaza starea algoritmului de
vizitare, care de multe ori acumuleaza rezultatele
obtinute in timpul vizitarii elementelor din structura.
D. Lucanu
10
Participanti 2/2
l
Element (Node)
defineste operatii de acceptare, care au ca argument
un vizitator
ConcreteElement (AssignmentNode,VariableRefNode)
implementeaza operatia de acceptare
ObjectStructure (Program)
poate enumera elementele sale
poate furniza o interfata la nivel inalt pentru un vizitator
care viziteaza elementele sale
poate fi un composite
D. Lucanu
11
Colaborari
D. Lucanu
12
Consecinte 1/2
l
l
13
Implementare 1/3
class Visitor {
public:
virtual void VisitElementA(ElementA*);
virtual void VisitElementB(ElementB*);
// and so on for other concrete elements
protected:
Visitor();
};
class Element {
public:
virtual ~Element();
virtual void Accept(Visitor&) = 0;
protected:
Element();
};
D. Lucanu
14
Implementare 2/3
class ElementA : public Element {
public:
ElementA();
virtual void Accept(Visitor& v) {
v.VisitElementA(this);
}
};
class ElementB : public Element {
public:
ElementB();
virtual void Accept(Visitor& v) {
v.VisitElementB(this);
}
};
D. Lucanu
15
Implementare 3/3
l
D. Lucanu
16
Aplicatie
l
D. Lucanu
17
Expresii
D. Lucanu
18
D. Lucanu
19
D. Lucanu
20
VisitorEval 1/2
class VisitorEval : public Visitor {
public:
...
void visitConstant(Constant* constant) {
tempVals.push(constant->getVal());
}
void visitVariable(Variable* variable) {
tempVals.push(
state->lookup(variable->getName())
);
}
D. Lucanu
21
VisitorEval 2/2
void visitProdExpression
(ProdExpression* prod) {
int temp = 1;
while (!tempVals.empty()) {
temp *= tempVals.top();
tempVals.pop();
}
cumulateVal += temp;
}
int getCumulateVal() {return cumulateVal;}
private:
State *state;
stack<int> tempVals;
int cumulateVal;
};
D. Lucanu
22
Clientul 1/2
Constant* one
Constant* two
Variable *a =
Variable *b =
= new Constant(1);
= new Constant(2);
new Variable("a");
new Variable("b");
ProdExpression* e1 = new
ProdExpression();
e1->add(one);
e1->add(a);
SumExpression* e2 = new SumExpression();
e2->add(e1);
e2->add(two);
e2->add(b);
D. Lucanu
23
Clientul 2/2
VisitorPrint visitorPrint;
e1.accept(visitorPrint);
1 a *
State st;
st.update("a", 10);
e1 = 10
D. Lucanu
24
Programe
D. Lucanu
25
D. Lucanu
26
VisitorExec 1/2
class VisitorExec : public Visitor {
public:
void visitDecl(Decl* decl) {
if (decl->getType() == "int") {
state->update(decl->getName(), 0);
}
}
void visitAssign(Assign* assign) {
VisitorEval evalExpr(0, state);
(assign->getRhs()).accept(evalExpr);
state->update(assign->getLhs(),
evalExpr.getCumulateVal());
}
D. Lucanu
27
VisitorExec 2/2
void visitConstant(Constant* constant) { }
void visitVariable(Variable* variable) { }
State& getState() {return state;}
private:
State *state;
};
D. Lucanu
28
Clientul 1/2
Decl* decl1 = new Decl("int", "a");
Decl* decl2= new Decl("int", "b");
Assign* assign1 = new Assign("a", e1);
Assign* assign2= new Assign("b", e2);
Pgm pgm;
pgm.insert(decl1);
pgm.insert(decl2);
pgm.insert(assign1);
pgm.insert(assign2);
D. Lucanu
29
Clientul 2/2
State st2;
VisitorExec visitorExec(&st2);
pgm.accept(visitorExec);
visitorExec.getState().print();
a |-> 0
b |-> 2
D. Lucanu
30
POO
Patternul
Observer
(prezentare bazata pe GoF)
31
Observator: :intentie
l
D. Lucanu
POO Principii
32
Observator :: motivatie
D. Lucanu
POO Principii
33
Observator :: aplicabilitate
l
D. Lucanu
POO Principii
34
Observator :: structura
D. Lucanu
POO Principii
35
Observator :: participanti
l
Subject
cunoaste observatorii (numar arbitrar)
Observer
defineste o interfata de actualizare a obiectelor ce
trebuie notificate de schimbarea subiectelor
ConcreteSubject
memoreaza starea de interes pentru observatori
trimite notificari observatorilor privind o schimbare
ConcreteObserver
mentine o referinta la un obiect ConcreteSubject
memoreaza starea care ar trebui sa fie consistenta cu
subiectii
D. Lucanu
POO Principii
36
Observator :: colaborari
linia
Linia
vietii
mesaj (apel
metoda)
diagrama de secventa
D. Lucanu
POO Principii
37
Observator :: consecinte
l
l
D. Lucanu
POO Principii
38
Observator :: implementare
l
l
l
D. Lucanu
POO Principii
39
Observator :: implementare
l
D. Lucanu
POO Principii
40
Observator :: implementare
l
D. Lucanu
POO Principii
41
Observator :: implementare
D. Lucanu
POO Principii
42
Observator :: cod
l
class Subject;
class Observer {
public:
virtual ~Observer();
virtual void update(Subject* theChangedSubject)
= 0;
metoda abstracta
protected:
Observer();
constructor ascuns (de ce?)
};
D. Lucanu
POO Principii
43
Observator :: cod
l
class Subject {
public:
virtual ~Subject();
virtual void attach(Observer*);
virtual void detach(Observer*);
virtual void notify();
protected:
Subject();
constructor ascuns (de ce?)
private:
List<Observer*> *_observers;
};
Relatia de asociere cu Observer
D. Lucanu
POO Principii
44
Observator :: cod
l
void Subject::attach(Observer* o) {
_observers->append(o);
}
void Subject::detach(Observer* o) {
_observers->remove(o);
}
void Subject::notify() {
ListIterator<Observer*> i(_observers);
for (i.first(); !i.isDone(); i.next()) {
i.currentItem()->update(this);
}
}
D. Lucanu
POO Principii
45
Observator :: cod
l
un subiect concret
POO Principii
46
Observator :: cod
un observator concret care mosteneste in plus o interfata grafica
class DigitalClock: public Widget, public Observer
{
mostenire multipla
public:
DigitalClock(ClockTimer*);
virtual ~DigitalClock();
virtual void update(Subject*);
// overrides Observer operation
virtual void draw();
// overrides Widget operation;
// defines how to draw the digital clock
private:
relatia de asociere cu
ClockTimer* _subject;
ConcreteSubject
};
l
D. Lucanu
POO Principii
47
Observator :: cod
l
DigitalClock::DigitalClock (ClockTimer* s) {
_subject = s;
_subject->attach(this);
}
DigitalClock::~DigitalClock () {
_subject->detach(this);
}
D. Lucanu
POO Principii
48
Observator :: cod
l
operatia de actualizare
void DigitalClock::update
(Subject* theChangedSubject) {
if (theChangedSubject == _subject) {
draw();
de ce se face
}
aceasta verificare?
}
void DigitalClock::draw () {
// get the new values from the subject
int hour = _subject->getHour();
int minute = _subject->getMinute();
// etc.
// draw the digital clock
}
D. Lucanu
POO Principii
49
Observator :: cod
l
un alt observator
POO Principii
50
MVC cu Observer
D. Lucanu
POO Principii
51
MVC
notif. sch.
interog. stare
Model
incapsuleaza starea aplicatiei
raspunde la interogari despre stare
expune functionalitatea modelului
notifica schimbarea starii
View
vizualizeaza modelul
cere actualizari de la model
trimite evenimentele utilizator la
controller
permite controllerului sa schimbe
modul de vizualizare
actiuni utilizator
selectie vizualizare
D. Lucanu
schimbare stare
not quite
UML
diagram
Controller
defineste comportarea aplicatiei
mapeaza actiunile utilizator pe
actulizare model
selecteaza vizulizarea
raspunsului
unul pentru fiecare functionalitate
D. Lucanu
53
mostenire
multipla
Pentru exemplul cu
Agenda inlocuieste
metoda listen()
D. Lucanu
POO Principii
54
D. Lucanu
55
mostenire
multipla
D. Lucanu
POO Principii
56
O fi
corect?
D. Lucanu
POO Principii
57
D. Lucanu
POO Principii
58
D. Lucanu
POO Principii
59
POO
Patternul
Iterator
(prezentare bazata pe GoF)
60
Iterator::intentie
l
D. Lucanu
61
Iterator::motivatie
initializeaza
elementul
curent la primul
element din lista
returneaza
elementul
curent din lista
D. Lucanu
testeaza daca
am trecut
dincolo de
ultimul element
al listei
62
Iterator::motivatie
l
D. Lucanu
63
Iterator polimorfic::motivatie
vom discuta
mai mult la
ObjectFactory
D. Lucanu
64
D. Lucanu
65
Iterator::structura
D. Lucanu
66
Iterator::participanti
l
Iterator
defineste interfata de accesare si traversare a
componentelor
ConcreteIterator
implementeaza interfata Iterator.
memoreaza pozitia curenta in traversarea agregatului
Aggregate
defineste interfata pentru crearea unui obiect Iterator
ConcreteAggregate
implementeaza interfata de creare a unui Iterator pentru a
intoarce o instanta proprie ConcreteIterator.
D. Lucanu
67
Iterator::consecinte
l
D. Lucanu
68
Iterator::implementare
l
l
l
D. Lucanu
69
Iterator::implementare
l
l
l
iteratori polimorfici
trebuie utilizati cu grija
clientul trebuie sa-i stearga ( ihm ... )
iteratorii pot avea acces privilegiat (C++ permite)
iteratori pentru componente compuse recursiv (a se
vedea patternul Composite)
external versus internal
iteratori nuli
pot usura traversarea obiectelor agregate cu structuri
mai complexe (de ex. arborescente)
prin definitie, un isDone() intoarce totdeauna true
pentru un iterator nul
D. Lucanu
70
Iterator::cod::interfete
l
D. Lucanu
71
Iterator::cod::interfete
l
interfata Iterator
metode
abstracte
D. Lucanu
72
Iterator::cod::implementare subclasa
l
73
Iterator::cod::implementare subclasa
template <class Item>
agregatul asociat
ListIterator<Item>::ListIterator
( const List<Item>* aList)
: _list(aList), _current(0) {
//nothing
initializare
}
template <class Item>
Item ListIterator<Item>::currentItem () const {
if (isDone()) {
throw IteratorOutOfBounds;
ietratorul curent in
afara marginilor
}
return _list->get(_current);
}
D. Lucanu
74
Iterator::cod::implementare subclasa
template <class Item>
void ListIterator<Item>::First () {
_current = 0;
}
pozitionarea pe
primul
75
Iterator::cod::utilizare
void PrintEmployees (Iterator<Employee*>& i) {
for (i.first(); !i.isDone(); i.next()) {
i.currentItem()->print();
schema de
parcurgere a unei
}
liste cu iteratori
}
List<Employee*>* employees;
// ...
ListIterator<Employee*> forward(employees);
ReverseListIterator<Employee*> backward(employees);
printEmployees(forward);
Iterator care parcurge lista invers;
printEmployees(backward);
D. Lucanu
76
Iteratorii in STL
l
l
D. Lucanu
77
Iteratorii in STL
l
D. Lucanu
78
Iteratorii in STL
l
D. Lucanu
79
Iteratorii in STL
l
list<int> L;
declarare
L.push_front(3);
insert_iterator<list<int> > ii(L, L.begin());
*ii++ = 0;
insereaza pe o si apoi avanseaza
*ii++ = 1;
copierea listei in fluxul cout
*ii++ = 2;
este echivalenta cu afisarea
copy(L.begin(), L.end(),
ostream_iterator<int>(cout, " "));
0 1 2 3
D. Lucanu
80
STL
List<Item>::Iterator<Item> i;
List<Item>::Iterator<Item>
i(list.begin());
i.first()
i.isDone()
i.next()
i.currentItem()
for (i.first();
!i.isDone();
i.next()) {...}
i = list.begin()
i == list.end()
++i
(i++)
*i
for (i = list.begin();
i != list.end();
++i) {...}
D. Lucanu
81
D. Lucanu
POO Principii
82
Iterator::cod::iteratori polimorfici
l
motivatie
sa presupunem ca utilizam mai multe tipuri de liste
SkipList<Employee*>* employees;
// ...
SkipListIterator<Employee*> iterator(employees);
PrintEmployees(iterator);
D. Lucanu
83
Iterator::cod::iteratori polimorfici
template <class Item>
class AbstractList
interfata la lista
{
public:
virtual Iterator<Item>* CreateIterator()
const = 0;
// ...
};
lista concreta
template <class Item>
Iterator<Item>* List<Item>::CreateIterator ()const
{
return new ListIterator<Item>(this);implementeaza
}
met. din interfata
D. Lucanu
84
Iterator::cod::iteratori polimorfici
// cunoastem numai AbstractList
AbstractList<Employee*>* employees;
pointer
// ...
Iterator<Employee*>* iterator =
employees->CreateIterator();
PrintEmployees(*iterator);
delete iterator; // noi suntem resp. pt. stergere!
l
D. Lucanu
85
private:
IteratorPtr(const IteratorPtr&);
IteratorPtr& operator=(const IteratorPtr&);
private:
Iterator<Item>* _i;
ascunde copierea si atribuirea
};
pentru a nu permite stergeri multiple
ale lui _i
D. Lucanu
86
AbstractList<Employee*>* employees;
// ...
IteratorPtr<Employee*>
iterator(employees->CreateIterator());
PrintEmployees(*iterator);
D. Lucanu
87
Iterator::cod::iterator intern
l
l
l
l
l
D. Lucanu
88
Iterator::cod::iterator intern
template <class Item>
class ListTraverser {
public:
ListTraverser(List<Item>* aList);
bool Traverse();
protected:
virtual bool ProcessItem(const Item&) = 0;
private:
ListIterator<Item> _iterator;
};
urmeaza a fi implementata cu
fuctii care proceseaza fiecare
element in parte
D. Lucanu
89
Iterator::cod::iterator intern
template <class Item>
ListTraverser<Item>::ListTraverser
( List<Item>* aList ) : _iterator(aList) { }
template <class Item>
bool ListTraverser<Item>::Traverse () {
bool result = false;
for ( _iterator.First();!_iterator.IsDone();
_iterator.Next() ) {
result = ProcessItem(_iterator.CurrentItem());
if (result == false) {
break;
}
}
return result;
}
D. Lucanu
90
Iterator::cod::iterator intern
class PrintNEmployees
: public ListTraverser<Employee*> {
public:
PrintNEmployees(List<Employee*>* aList, int n) :
ListTraverser<Employee*>(aList),
_total(n), _count(0)
{ /* nothing /* }
protected:
bool ProcessItem(Employee* const&);
private:
int _total;
int _count;
};
D. Lucanu
91
Iterator::cod::iterator intern
bool PrintNEmployees::ProcessItem
(Employee* const& e) {
_count++;
e->Print();
return _count < _total;
}
l
utilizare
List<Employee*>* employees;
// ...
PrintNEmployees pa(employees, 10);
pa.Traverse();
D. Lucanu
92
Iterator::cod::iterator intern
l
D. Lucanu
93
Iterator::cod::iterator intern
l
D. Lucanu
94
Iterator::cod::iterator intern
template <class Item>
void FilteringListTraverser<Item>::Traverse () {
bool result = false;
for ( _iterator.First(); !_iterator.IsDone();
_iterator.Next() ) {
if (TestItem(_iterator.CurrentItem())) {
result = ProcessItem(_iterator.CurrentItem());
if (result == false) {
break;
}
}
}
return result;
}
D. Lucanu
95