lunes, 4 de mayo de 2015

Observer

Observer

Propósito

Definir una dependencia de uno-a-muchos entre objetos, de manera que cuando un objeto cambia de estado todos los que dependan de él sean notificados y actualizados automáticamente.

También conocido como: Dependents, Publish-Subscribe

Motivación

Un efecto secundario común en un sistema particionado en una colección de clases que cooperan es la necesidad de mantener la coherencia entre los objetos relacionados. No se desea lograr la coherencia, haciendo clases estrechamente unidas ya que esto reduce la reutilización.
El patrón Observer describe como estableces las relaciones entre las clases. Los objetos claves en este patrón son el sujeto y el observador. Un sujeto puede tener cualquier número de observadores dependientes. Todos los observadores son notificados cuando el sujeto se somete a un cambio de estado. Como respuesta, cada observador consulta el sujeto pata sincronizar este estado con los estados de los demás sujetos.

Aplicabilidad

Aplicamos el patrón Observer cuando se tenemos alguna de estas situaciones:

  • Cuando una abstracción tiene dos aspectos, uno depende del otro. Encapsular estos aspectos en objetos separados permitirá variarlos y reutilizarlos de forma independiente.
  • Cuando un cambio en un objeto requiere cambiar otros, y no se conoce cuantos objetos necesitan ese cambio.
  • Cuando un objeto debe ser capaz de notificar a otros objetos sin suponer acerca de que son esos objetos. En otras palabras, no se quiere que los objetos estén perfectamente acoplados.
Estructura

Participantes

Subject
  • Conoce a sus observadores. Cualquier número de objetos Observer pueden observar un subject.
  • Provee una interfaz para conectar y desconectar objetos Observer.
Observer
  • Define una interfaz actualizada para objetos que deben ser notificados de los cambios en un sujeto (subject)
ConcreteSubject
  • Almacena el estado de los objetos ConcreteObserver interesados.
  • Envía una notificación a sus observadores cuando su estado cambia.
ConcreteObserver
  • Mantiene una referencia a un objeto ConcreteSubject.
  • Almacena el estado que debe mantener consistencia con el sujeto.
  • Implementa la interfaz actualizada de Observer para mantener su estando en concordancia con el del sujeto.
Colaboraciones


  • El objeto observado notifica a sus observadores cada vez que ocurre un cambio, con la finalidad de que el estado de ambos sea consistente.
  • Después de ser informado de un cambio en el objeto observado, cada observador concreto puede pedirle la información que necesita para reconciliar su estado con el de aquél.
Consecuencias

EL patrón Observer permite variar los sujetos y los observadores independientemente. Se puede rehusar sujetos sin el rehúso de observadores y viceversa. Permite agregar observadores sin modificar el sujeto o los observadores.

Algunas ventajas y desventajas del patrón Observer son:
  1. Acoplamiento abstracto entre Subject y Observer. Todo lo que un objeto sabe de sus observadores es que tiene una lista de objetos que satisfacen la interfaz Observer. Con lo que podrían incluso pertenecer a dos capas distintas de la arquitectura de la aplicación.
  2. No se especifica el receptor de una actualización. Se envía a todos los objetos interesados
  3. Actualizaciones inesperadas. Se podrían producir actualizaciones en cascada muy ineficientes.
Implementación

Varias cuestiones relacionadas con los mecanismos de dependencias son discutidas a la hora de implementar el patrón Observer:
  1. Correspondencia entre objetos observados y observadores. En vez de mantener una colección con referencias explícitas a los observadores en el objeto observado, sería posible hacerlo con una tabla hash que relacionase ambos. Útil cuando hay muchos objetos a observar y pocos observadores, para reducir los costes de Almacenamiento.
  2. Observar más de un objeto. Cuando un observador dependa de más de un objeto, es necesario ampliar la información de la operación update. Por ejemplo, incluyéndose el objeto observado a sí mismo como parámetro, para que el observador pueda discriminar.
  3. ¿Quién lanza la actualización? Es decir, ¿quién se encarga de llamar a notify? El objeto observado, cada vez que cambia su estado, puede dar lugar a actualizaciones ineficientes, Los clientes puede eliminar actualizaciones intermedias innecesarias, más propenso a errores: los clientes pueden olvidarse de llamar a notify.
  4. Evitar protocolos de actualización específicos de los observadores. Modelo push: El objeto observado envía información detallada a sus observadores sobre el cambio producido, (La necesiten o no). Modelo pull: Tan sólo avisa de que cambió, Los observadores le solicitan la información que necesiten.
  5. Especificar explícitamente el aspecto que varía. Podemos extender la interfaz de registro de observadores para que éstos indiquen los eventos que les interesan. Cuando se produzca un evento, el objeto observado informará sólo a los observadores interesados en ese evento.
Código de ejemplo

public class ClaseObservador extends Observable{
  
 private int colorSeleccionado;
 private String color;
  
 public ClaseObservador(){
   
 }
 public void setColorSeleccionado(int i) {
  this.colorSeleccionado = i;
  setChanged();
     notifyObservers();
 }
 public int getColorSeleccionado() {
  return colorSeleccionado;
 }
 public void setColor(String color) {
  this.color = color;
 }
 public String getColor() {
  return color;
 }
}
-------------------------------------------------------------------------
public static void main(String[] args)
{
  ClaseObservador observador=new ClaseObservador();
  VentanaOpciones miVentanaOpciones=new VentanaOpciones(observador);
  VentanaColor miVentanaColor=new VentanaColor(observador);
  VentanaSeleccion miVentanaSeleccion=new VentanaSeleccion(observador);
  
  /**Aqui se Agregan los observadores*/
  observador.addObserver(miVentanaColor);
  observador.addObserver(miVentanaSeleccion);
  observador.addObserver(miVentanaOpciones);
}

Usos conocidos
  • Uno de los primeros usos conocidos del patrón Observer aparece en Smalltalk Model/View/Controller.
  • Delegación de eventos en Java.
Patrones relacionados

Mediator. Para encapsular actualizaciones semánticas complejas, el ChangeManager actúa como mediador entre sujetos y observadores.
Singleton. El ChangeManager puede usar el patrón Singleton para que sea único y accesible a nivel global.

Referencias
  • Design Patterns Elements of Reusable Object-Oriented Software, GoF.
  • http://kybele.escet.urjc.es/documentos/SI/Patrones/16_Observer.ppt
  • http://sophia.javeriana.edu.co/~lcdiaz/ingSw2006-3/ptnObserver_dAli.ppt
  • http://www.cesaracebal.com/docencia/asignaturas/aaswiki/_media/patrones/observer-mvc.pdf?id=patrones%3Amvc&cache=cache

No hay comentarios:

Publicar un comentario