Professional Documents
Culture Documents
Ooup 3 More Patterns
Ooup 3 More Patterns
Siniša Šegvić
Sveučilište u Zagrebu
Fakultet elektrotehnike i računarstva
Zavod za elektroniku, mikroelektroniku
računalne i inteligentne sustave
→ 1/121
TVORNICE: UVOD
Do sada smo naučili da apstraktna sučelja mogu znatno pospješiti
nadogradivost programskog sustava
Konkretna
Kontekst
strategija
Apstraktna
strategija
Primjenljivost:
□ točno jedna, globalno pristupačna instanca
□ jedinstvenu instancu prikladno instancirati s odgodom
(kad se javi potreba)
// explicit form :
Iterator < Map . Entry < String , Integer >> it = mymap . entrySet (). iterator ();
while ( it . hasNext ()) {
Map . Entry < String , Integer > item = it . next ();
System . out . println ( item . getKey () + " " + item . getValue ());
}
// implicit form :
for ( Map . Entry < String , Integer > item : mymap . entrySet ()) {
System . out . println ( item . getKey () + " " + item . getValue ());
}
// explicit form :
for ( MyMap :: const_iterator it = mymap . begin ();
it != mymap . end (); ++ it )
{
std :: cout <<it -> first <<" " <<it -> second <<"\n" ;
}
# mi kažemo :
for key in mymap :
print ( key , mymap [ key ])
Detalji:
□ prednosti se očituju i ako nema potrebe za polimorfnim pristupom
(jasnija upotreba)
□ u različitim jezicima koriste se različite varijante polimorfizma (C++:
statički, Java: dinamički)
def variance3 (L ):
mean = sum (L )/ len (L)
g=SqrdevGenFun(L,mean)
return sum (g )/ len (L)
camera
MyApp AbstractCamera libdc1394
...
...
pcamera->getFrame()
pcamera->getFrame()
...
... handle
Camera1394DCAM
...
...
getFrame()
dc1394_capture_dequeue(handle,
dc1394_capture_dequeue(handle, ...)
...)
...
...
handle
handle_
CameraV4L V4L (kernel module)
getFrame() open()
ioctl()
state ...
...
...
hh == handle_
handle_
ioctl(h,
ioctl(h, VIDIOCMCAPTURE,
VIDIOCMCAPTURE, &vmap_);
&vmap_);
ioctl(h,
ioctl(h, VIDIOCSYNC,
VIDIOCSYNC, &fb);
&fb);
...
...
Dobitci:
□ transparentna interoperabilnost
□ prilagođeno sučelje otežava neželjene obrasce korištenja vanjskih
komponenata
□ klijenti oblikuju u okviru domene, ne implementacije
class Horse :
def __init__ ( self , name ):
self . name = name
d2 = Dog (" Atila ")
def neigh ( self ):
h1 = Horse (" Caesar " )
return " Njihihi !"
o1 = PoliceAdapter ( h1 , h1 . neigh )
# class PoliceHorse ...
o2 = PoliceAdapter ( d2 , d2 . bark )
# would be repetition !
report ( o1 ) # works !
class PoliceAdapter :
report ( o2 ) # works !
def __init__ ( self , adaptee , greet ):
self . adaptee = adaptee
self . greet = greet # magic !
Motivacijski primjer:
□ Grupiranje pojedinačnih elemenata vektorskog crteža
(tekst, linije, teksturirani poligoni, rasterske slike, ...)
□ kompozitni objekt postaje ``punopravni'' element crteža
(tretira se kao pojedinačni objekti: iscrtavanje, pomicanje, atributi)
□ operacije nad kompozitnim objektom delegiraju se sastavnim
dijelovima!
aGroup
Client Component
operation()
children
`
Leaf Composite
Client Component
operation()
getComposite() return
return null;
null;
children
Leaf Composite
...
...
operation() for
for gg in
in children:
children:
operation() g.operation()
g.operation()
iterator() ...
...
add(Component)
remove(Component)
return
return this;
this;
getComposite()
Client Component
operation()
iterator() children
getComposite()
return
return children.iterator()
children.iterator()
Leaf Composite
operation()
operation() iterator()
add(Component)
remove(Component)
getComposite()
Client Component
operation()
iterator() ...
...
add(Component) throw
throw “unsupported!”
“unsupported!”
...
...
remove(Component)
`
children
Leaf Composite
Client Component
operation()
iterator()
add(Component)
remove(Component) children
Leaf Composite
operation() operation()
iterator() ...
...
add(Component) throw
throw “unsupported!”
“unsupported!”
remove(Component) ...
...
Motivacijski primjer:
□ Senzorski element povremeno otvara bežičnu vezu i prima
konekcije udaljenih klijenata
□ Veza može biti u tri stanja: zatvorenom, pripremnom i
uspostavljenom
□ Ponašanje komunikacijske komponente ovisi o stanju veze:
npr, TCPConnection::send() nema smisla ako veza nije uspostavljena
□ Želimo rano detektirati krivo korištenje komunikacijske komponente
□ Želimo omogućiti jednostavno širenje komunikacijskog protokola
TCPConn
state `
TCPState
`
` ` ` `
class StateMachine : c
class StateA :
def state ( self ): return "A" 1
def event0 ( self ):
self . __class__ = StateMachine . StateB 1
def event1 ( self ):
1 0
self . __class__ = StateMachine . StateC
class StateB :
def state ( self ): return "B" 0
def event0 ( self ): a b
self . __class__ = StateMachine . StateA 0
def event1 ( self ):
self . __class__ = StateMachine . StateC
class StateC : s= StateMachine ()
def state ( self ): return "C" >>> s . state ()
def event0 ( self ): 'A '
self . __class__ = StateMachine . StateA >>> s . event0 ()
def event1 ( self ): >>> s . state ()
self . __class__ = StateMachine . StateB 'B '
def __init__ ( self ): >>> s . event0 ()
self . __class__ = StateMachine . StateA >>> s . state ()
'A '
Motivacijski primjer:
□ Često je korisno odgoditi kreiranje teških objekata
□ pri učitavanju velikog dokumenta, ne učitati odmah i sve slike
□ cilj: omogućiti korisniku što brži početak rada (produktivnost ↑)
□ sliku učitavamo tek kad nam stvarno treba (npr, treba je iscrtati)
□ primjer koncepta odgođenog izračunavanja (lazy evaluation)
□ ideja: postići transparentni pametni pristup
anImageFilter
anImgPtrProxy Image
ptrImagePixel
realImagePtr
ImgPtrProxy
assert(isWithin());
assert(isWithin());
operator*() return
return *realPtr_;
*realPtr_;
setxy(x,y) realPtr_
realPtr_ == origin_
origin_
++ y*szLine_
y*szLine_ ++ x;
x;
origin_
realPtr_
szLine_
height_
Motivacijski primjer:
□ Program za vektorsku grafiku koji barata s poligonima, tekstom i
rasteriziranim slikama
□ Fokus: metoda za iscrtavanje grafičkog objekta
□ Želja: podržati različite biblioteke za crtanje te omogućiti
eksportiranje u različite grafičke formate
□ Monolitna hijerarhija problematična:
□ sklonost kvadratnom porastu broja razreda: PolygonWin32,
PolygonSVG, ..., EllipseWin32, EllipseSVG, ...
□ potiče vezivanje kôda uz jednu platformu
□ ideja: dvije osi varijacije modelirati odvojenim hijerarhijama
Obrasci → Most 76/121
MOST: MOTIVACIJSKI PRIMJER
`
imp `
Shape Renderer
`
`
move(x,y) cx_+=dx;
cx_+=dx;
cy_+=cy; drawLine()
applyStyle() cy_+=cy;
drawText()
draw()
` drawImage()
cx_, cy_
` `
RenderXWin RenderSVG
` `
`
imp `
operation1() ...
...
operation()
imp->operation();
imp->operation();
...
...
AbstractionRefined
` `
`
Namjera:
□ Odrediti razred novog objekta polimorfnim kloniranjem prototipa
□ operator new considered harmful
Motivacijski primjer:
□ program kadrovske službe obračunava plaće, godišnje odmore, itd
□ zadatci ovise o razredu zaposlenika (održavanje, inženjer, direktor)
□ ne želimo zadatke smještati u sučelje zaposlenika zbog načela
jedinstvene odgovornosti
□ poziv ovisi o (i) razredu zaposlenika i (ii) razredu zadatka
Shape Renderer
`
`
move(x,y) cx_+=dx;
cx_+=dx;
cy_+=cy; drawLine()
applyStyle() cy_+=cy;
drawText()
draw(r)
` drawImage()
cx_, cy_
` `
RenderXWin RenderSVG
` `
Application Document
createDocument() ...
newDocument() docs_.push_back(
createDocument());
...
pDocs_
MyApplication
MyDocument
createDocument() return new MyDocument;
izravna ovisnost
Promatrač ovisnost prema
osnovnom tipu
Model
Pogled Upravljač
(Kompozit)
Stanje, Strategija
ili Naredba