Sunteți pe pagina 1din 20

Tcnicas de Programacin - Curso 2008/09

(Esther Guerra Snchez)


Patrones de Diseo
Patrn de comportamiento Observer
Observer
Propsito
Define una dependencia de uno-a-muchos entre
objetos de forma que, cuando un objeto cambia
de estado, se notifica a los objetos dependientes
para que se actualicen automticamente.
Tambin conocido como dependents, publish-
subscribe
Observer
Motivacin
Mantener la consistencia entre objetos relacionados, sin
aumentar el acoplamiento entre clases
Ej: separacin de la capa de presentacin en una interfaz
de usuario de los datos de aplicacin subyacentes
A
B
C
D
0
10
20
30
40
A B C D
a: 40%
b: 25%
c: 15%
d: 20%
A B C D
X 60 20 15 5
Y 40 25 15 20
Z 10 10 20 60
Not i f i caci n de cambi o
Consul t a, modi f i caci n
Observer
Aplicabilidad
Usa el patrn Observer:
Cuando una abstraccin tiene dos aspectos, y uno
depende del otro. Encapsular los aspectos en objetos
distintos permite cambiarlos y reutilizarlos.
Cuando cambiar un objeto implica cambiar otros, pero
no sabemos exactamente cuntos hay que cambiar
Cuando un objeto debe ser capaz de notificar algo a
otros sin hacer suposiciones sobre quines son dichos
objetos. Esto es, cuando se quiere bajo acoplamiento.
Observer
Estructura
Observer
+ update()
Subject
+attach(Observer)
+detach (Observer)
+notify ()
forall o in observers:
o.update();
ConcreteSubject
- subjectState
+getState()
+setState()
ConcreteObserver
- observerState
+update()
return subjectState;
observers
* 0..1
subject
0..1
observerState =subject.getState();
Observer
Participantes
Subject:
conoce a sus observadores, que pueden ser un nmero arbitrario
proporciona una interfaz para aadir y quitar objetos observadores
Observer:
define la interfaz de los objetos a los que se deben notificar
cambios en un sujeto
ConcreteSubject:
almacena el estado de inters para sus observadores
enva notificaciones a sus observadores cuando su estado cambia
ConcreteObserver:
mantiene una referencia a un ConcreteSubject
almacena el estado del sujeto que le resulta de inters
implementa la interfaz de Observer para mantener su estado
consistente con el del sujeto
Observer
Colaboraciones
:ConcreteSubject
co1
:ConcreteObserver
co2
:ConcreteObserver
setState()
notify()
update()
getState()
getState()
update()
(sujeto con dos observadores)
Observer
Colaboraciones
:ConcreteSubject
co
:ConcreteObserver
setState()
notify()
update()
getState()
(sujeto con un nmero arbitrario de observadores)
loop
[for each co in observers]
Observer
Consecuencias
Permite modificar sujetos y observadores de manera independiente
Permite reutilizar un sujeto sin reutilizar sus observadores, y viceversa
Permite aadir observadores sin tener que cambiar el sujeto ni los
dems observadores
Acoplamiento abstracto entre el sujeto y el observador. El sujeto no
sabe la clase concreta de sus observadores (acoplamiento mnimo).
Soporte para broadcast. El sujeto enva la notificacin a todos los
observadores suscritos. Se pueden aadir/quitar observadores.
Actualizaciones inesperadas. Una operacin en el sujeto puede
desencadenar una cascada de cambios en sus observadores. El
protocolo no ofrece detalles sobre lo que ha cambiado.
Observer
Implementacin
Correspondencia entre sujetos y observadores
Usualmente, el sujeto guarda una referencia a sus observadores
Costoso si hay muchos sujetos y pocos observadores. En ese caso:
usar tabla hash: menor coste en espacio, pero mayor coste en tiempo
Observar ms de un sujeto (ej. hoja de clculo con 2 fuentes de datos)
Extender la interfaz de actualizacin para que el observador sepa qu
sujeto cambi de estado (por ej. pasar el sujeto en la llamada a update).
s1:Sujeto
s2:Sujeto
s3:Sujeto
s4:Sujeto
o:Observador
hash
intermedia
(s1, s3 y s4 no incurren en gasto de almacenamiento de observadores)
Observer
Implementacin
Quin dispara la actualizacin llamando a notify?
El sujeto desde aquellos mtodos que cambian su estado
ventaja: las clases cliente no tienen que hacer nada
inconveniente: no es ptimo si hay varios cambios de estado seguidos
Las clases cliente
ventaja: se puede optimizar llamando a notify tras varios cambios
inconveniente: los clientes tienen la responsabilidad de llamar a notify
Referencias perdidas a sujetos que se han eliminado
Se puede evitar notificando la eliminacin del sujeto a sus observadores
En general, eliminar los observadores del sujeto eliminado no es una
opcin
Observer
Implementacin
Asegurarse de la consistencia del sujeto antes de una notificacin
Cuidado con las operaciones heredadas!
cl ass Cl aseSuj et oBase {
voi d oper aci on ( i nt val or ) {
_mi Var += val or ; / / act ual i za el est ado
not i f y( ) ; / / di spar a l a not i f i caci n
}
}
cl ass Mi Suj et o ext ends Cl aseSuj et oBase {
voi d oper aci on ( i nt val or ) {
super . oper aci on( val or ) ; / / di spar a l a not i f i caci n
_mi Var += val or ; / / act ual i za el est ado ( t ar de)
}
}
Soluciones:
documentar los mtodos que envan notificaciones
patrn de diseo Template Method
Observer
Implementacin
Asegurarse de la consistencia del sujeto antes de una notificacin
Soluciones:
documentar los mtodos que envan notificaciones
patrn de diseo Template Method
cl ass Cl aseSuj et oBase {
voi d oper aci on ( i nt val or ) {
_mi Var += val or ;
}
voi d oper aci onNot i f y ( i nt val or ) {
sel f . oper aci on( val or ) ; / / ej ecut a l a oper aci n
sel f . not i f y( ) ; / / di spar a l a not i f i caci n
}
}
cl ass Mi Suj et o ext ends Cl aseSuj et oBase {
voi d oper aci on ( i nt val or ) {
super . oper aci on( val or ) ;
_mi Var += val or ;
}
}
los clientes llaman a oper aci onNot i f y
en vez de a oper aci on
Observer
Implementacin
Evitar protocolos de actualizacin especficos del observador
Modelo pull: el sujeto enva lo mnimo, los observadores piden lo necesario
inconveniente: puede ser poco eficiente
Modelo push: el sujeto enva informacin detallada del cambio, aunque los
observadores no la necesiten.
inconveniente: observadores menos reutilizables
Especificar las modificaciones de inters explcitamente
Hacer update ms eficiente, haciendo que los observadores se registren
slo en los eventos que les interesan
Los observadores se subscriben a aspectos del sujeto
cl ass Subj ect {
publ i c at t ach ( Obser ver o, Aspect a) { . . . }
}
cl ass Obser ver {
publ i c updat e ( Subj ect s, Aspect a) { . . . }
}
Observer
Implementacin
Encapsular la semntica de actualizaciones complejas
Cuando la relacin de dependencia entre sujetos y observadores es
compleja, se puede usar un objeto intermedio para la gestin de cambios
Minimiza el trabajo de reflejar cambios de los sujetos en los observadores
Ej.: si se actualizan varios sujetos, hay que asegurar que los observadores
se actualizan slo despus del cambio en el ltimo sujeto
Subject
+attach (Observer o)
+detach (Observer)
+notify ()
Observer
+ update(Subject)
subjects
* *
chman
1
ChangeManager
+ register (Subject,Observer)
+ unregister (Subject,Observer)
+ notify ()
Subject-Observer mapping
observers
chman.register(this,o);
SimpleChangeManager
+register (Subject,Observer)
+unregister (Subject,Observer)
+notify ()
DAGChangeManager
+register (Subject,Observer)
+unregister (Subject,Observer)
+notify ()
forall s in subjects:
forall o in s.observers:
o.update(s)
chman.notify();
Marcar observers a actualizar.
Actualizar observers marcados.
1
Observer
Ejemplo
Observer
+ update()
Subject
+attach(Observer)
+detach (Observer)
+notify ()
Datasource
- a, b, c, d: double
+getState(): double[4]
+setState(double[4]): void
Fila
- data: double[4]
+update()
observers
* 1
1
*
Barras
- a, b, c, d: double
+update()
Circular
- a, b, c, d: double
+update()
* *
1 1
Observer
Cdigo de ejemplo
publ i c abst r act cl ass Subj ect {
pr ot ect ed Li st <Obser ver > _obser ver s;
publ i c Subj ect ( ) {
_obser ver s =
new Li nkedLi st <Obser ver >( ) ;
}
publ i c voi d at t ach( Obser ver o) {
_obser ver s. add( o) ;
}
publ i c voi d det ach( Obser ver o) {
_obser ver s. r emove( o) ;
}
publ i c voi d not i f y( ) {
I t er at or <Obser ver > i t ;
i t = _obser ver s. i t er at or ( ) ;
whi l e ( i t . hasNext ( ) )
i t . next ( ) . updat e( ) ;
}
}
publ i c cl ass Dat asour ce
ext ends Subj ect {
pr i vat e doubl e _a, _b, _c, _d;
publ i c doubl e[ ] get St at e ( ) {
doubl e[ ] d = new doubl e[ 4] ;
d[ 0] = _a;
d[ 1] = _b;
d[ 2] = _c;
d[ 3] = _d;
r et ur n d;
}
publ i c voi d set St at e( doubl e[ ] d) {
_a = d[ 0] ;
_b = d[ 1] ;
_c = d[ 2] ;
_d = d[ 3] ;
t hi s. not i f y( ) ;
}
}
Observer
Cdigo de ejemplo
publ i c abst r act cl ass Obser ver {
pr ot ect ed Subj ect _subj ect ;
publ i c Obser ver ( Subj ect s) {
_subj ect = s;
_subj ect . at t ach( t hi s) ;
}
publ i c abst r act voi d updat e ( ) ;
}
publ i c cl ass Fi l a ext ends Obser ver {
pr i vat e doubl e[ ] _dat a;
publ i c Fi l a ( Subj ect s) {
super ( s) ;
_dat a = new doubl e[ 4] ;
}
publ i c voi d updat e ( ) {
doubl e[ 4] dat a;
dat a =
( ( Dat asour ce) _subj ect ) . get St at e( ) ;
f or ( i nt i =0; i <4; i ++)
_dat a[ i ] = dat a[ i ] ;
t hi s. r edr aw( ) ;
}
publ i c voi d r edr aw ( ) { . . . }
}
Observer
Cdigo de ejemplo
publ i c abst r act cl ass Obser ver {
publ i c abst r act voi d updat e ( ) ;
}
publ i c cl ass Fi l a ext ends Obser ver {
pr i vat e Dat asour ce _subj ect ;
pr i vat e doubl e[ ] _dat a;
publ i c Fi l a ( Dat asour ce s) {
_subj ect = s;
_subj ect . at t ach( t hi s) ;
_dat a = new doubl e[ 4] ;
}
publ i c voi d updat e ( ) {
doubl e[ 4] dat a;
dat a = _subj ect . get St at e( ) ;
f or ( i nt i =0; i <4; i ++)
_dat a[ i ] = dat a[ i ] ;
t hi s. r edr aw( ) ;
}
publ i c voi d r edr aw ( ) { . . . }
}
Observer
En java
La interfaz j ava. ut i l . Obser ver
voi d updat e ( Obser vabl e o, Obj ect ar g)
La clase j ava. ut i l . Obser vabl e
Obser vabl e( )
voi d addObser ver ( Obser ver )
i nt count Obser ver s( )
voi d del et eObser ver ( Obser ver o)
voi d del et eObser ver s( )
voi d not i f yObser ver s( )
voi d not i f yObser ver s( Obj ect ar g)
bool ean hasChanged( )
voi d cl ear Changed( )
voi d set Changed( )

S-ar putea să vă placă și