El patrón Observer puede ser utilizado cuando hay objetos que dependen de otro, necesitando ser notificados en caso de que se produzca algún cambio en él.
Se utilizarán los métodos agregarObservador() y quitarObservador() de la clase abstracta UnObservado para registrar en una lista qué objetos de tipo UnObservador deberán ser notificados o dejar de serlo cuando se produzca algún cambio en él (en tal caso recorrerá dicha lista para enviar una notificación a cada uno de ellos).
El mensaje será enviado a UnObservador (que implementa la interface IObservador) utilizando su método observadoActualizado().
Veamos a continuación un ejemplo sencillo en lenguaje Java en el cual cuando se produce un cambio en el observado éste envía una notificación a los observadores, que simplemente mostrarán un mensaje al recibirla.
Main.java:
package Observer;
public class Main
{
public static void main(String[] args)
{
// Instanciar el objeto que será Observado
UnObservado objObservado = new UnObservado();
// Instanciar y registrar un Observador
UnObservador objObservadorPepe = new UnObservador("Pepe");
objObservado.agregarObservador(objObservadorPepe);
// Instanciar y registrar otro Observador
UnObservador objObservadorJuan = new UnObservador("Juan");
objObservado.agregarObservador(objObservadorJuan);
// Instanciar y registrar otro Observador
UnObservador objObservadorMarta = new UnObservador("Marta");
objObservado.agregarObservador(objObservadorMarta);
}
}
Observado.java:
package Observer;
import java.util.ArrayList;
public abstract class Observado
{
private ArrayList<IObservador> observadores = new ArrayList<IObservador>();
// ---------------------------------
public Observado() {
}
// ---------------------------------
public void agregarObservador(IObservador o)
{
observadores.add(o);
// Según nuestro ejemplo, cada vez que se agregue un nuevo observador, los existentes serán notificados
notificarObservadores();
}
// ---------------------------------
public void eliminarObservador(IObservador o) {
observadores.remove(o);
}
// ---------------------------------
public void notificarObservadores()
{
// Enviar la notificación a cada observador a través de su propio método
for (IObservador obj : observadores) {
obj.observadoActualizado();
}
}
}
UnObservado.java:
package Observer;
public class UnObservado extends Observado
{
public UnObservado() {
}
}
IObservador.java:
package Observer;
public interface IObservador
{
public void observadoActualizado();
}
UnObservador.java:
package Observer;
public class UnObservador implements IObservador
{
private String nombre;
// ---------------------------------
public UnObservador(String nombre) {
this.setNombre(nombre);
System.out.println("Observador [" + this.nombre + "] creado");
}
// ---------------------------------
public String getNombre() {
return this.nombre;
}
// ---------------------------------
public void setNombre(String nombre) {
this.nombre = nombre;
}
// ---------------------------------
@Override
public void observadoActualizado() {
System.out.println("Observador [" + this.getNombre() + "] recibe la notificación");
}
}
Al ejecutarlo obtendríamos como resultado:
EXPLICACIÓN:
- Al inicio del programa se crea el objeto que será observado así como tres objetos observadores del anterior, que se agregan a la lista del observado.
- Cuando se produce un cambio en el observado (cuando se le agrega un nuevo observador) éste envía una notificación a los observadores (sin pasar ningún tipo de parámetro en este ejemplo).
En este otro ejemplo mostramos una forma más recomendable de utilizar este patrón.
Main.java:
package Observer2;
public class Main
{
public static void main(String[] args)
{
// Instanciar el objeto que será Observado
UnObservado objObservado = new UnObservado();
objObservado.agregarObservador( new UnObservador() );
objObservado.agregarObservador( new UnObservador() );
objObservado.agregarObservador( new UnObservador() );
objObservado.setNombre("PEPE");
objObservado.setNombre("MARTA");
}
}
Observado.java:
package Observer2;
import java.util.ArrayList;
public abstract class Observado
{
private ArrayList<IObservador> observadores = new ArrayList<IObservador>();
// ---------------------------------
public Observado() {
}
// ---------------------------------
public void agregarObservador(IObservador o) {
observadores.add(o);
}
// ---------------------------------
public void eliminarObservador(IObservador o) {
observadores.remove(o);
}
// ---------------------------------
public void notificarObservadores( Object valor )
{
// Enviarles la notificación a cada observador a través de su propio método
for (IObservador obj : observadores) {
obj.observadoActualizado(this, valor);
}
}
}
UnObservado.java:
package Observer2;
public class UnObservado extends Observado
{
private String nombre = "";
// ---------------------------------
public UnObservado() {
}
// ---------------------------------
public String getNombre() {
return this.nombre;
}
// ---------------------------------
public void setNombre(String nombre) {
this.nombre = nombre;
// Enviarles la notificación a cada observador a través de su propio método
this.notificarObservadores( nombre );
}
}
IObservador.java:
package Observer2;
public interface IObservador
{
public void observadoActualizado( Observado objObservado, Object valor );
}
UnObservador.java:
package Observer2;
public class UnObservador implements IObservador
{
public UnObservador() {
}
// ---------------------------------
@Override
public void observadoActualizado( Observado objObservado, Object valor ) {
System.out.println("El valor del objeto ha cambiado a [" + ((String) valor) + "]");
}
}
Al ejecutarlo obtendríamos como resultado:
EXPLICACIÓN:
- Al inicio del programa se crea el objeto que será observado así como tres observadores que se agregan a su lista.
- Se modifica por dos veces un valor del objeto observado.
- Cuando se produce un cambio en el observado (se asigna un nuevo valor al atributo nombre), en el mismo método setNombre() se llama al método notificarObservadores() (que a su vez llama al método observadoActualizado() que implementan los objetos observadores) para enviarles una notificación, junto con una referencia a sí mismo observado y el valor modificado.
En este último ejemplo, cuando se produce un cambio en el observado éste envía una notificación a los observadores (que en este caso al ser instanciados guardan una referencia a él) los cuales se encargarán de consultarle directamente para averiguar la modificación producida.
Main.java:
package Observer3;
public class Main
{
public static void main(String[] args)
{
// Instanciar el objeto que será Observado
UnObservado objObservado = new UnObservado();
// Instanciar los observadores, pasándoles como parámetro el que será Observado
new UnObservador( objObservado );
new UnObservador( objObservado );
new UnObservador( objObservado );
objObservado.setNumero(55);
}
}
Observado.java:
package Observer3;
import java.util.ArrayList;
public abstract class Observado
{
private ArrayList<IObservador> observadores = new ArrayList<IObservador>();
// ---------------------------------
public Observado() {
}
// ---------------------------------
public void agregarObservador(IObservador o) {
observadores.add(o);
}
// ---------------------------------
public void eliminarObservador(IObservador o) {
observadores.remove(o);
}
// ---------------------------------
public void notificarObservadores()
{
// Enviarles la notificación a cada observador a través de su propio método
for (IObservador obj : observadores) {
obj.observadoActualizado();
}
}
}
UnObservado.java:
package Observer3;
public class UnObservado extends Observado
{
private int numero = 0;
// ---------------------------------
public UnObservado() {
}
// ---------------------------------
public int getNumero() {
return this.numero;
}
// ---------------------------------
public void setNumero(int numero) {
this.numero = numero;
// Según nuestro ejemplo, cada vez que se agregue un nuevo observador, los existentes serán notificados
notificarObservadores();
}
}
IObservador.java:
package Observer3;
public interface IObservador
{
public void observadoActualizado();
}
UnObservador.java:
package Observer3;
public class UnObservador implements IObservador
{
private UnObservado objObservado;
// ---------------------------------
public UnObservador( UnObservado objObservado ) {
this.objObservado = objObservado;
objObservado.agregarObservador(this);
}
// ---------------------------------
@Override
public void observadoActualizado() {
System.out.println("El valor del objeto Observado ha cambiado a [" + this.objObservado.getNumero() + "]");
}
}
Al ejecutarlo obtendríamos como resultado:
EXPLICACIÓN:
- Se crea el objeto que será observado junto con tres observadores del anterior, a los que les pasa como parámetro una referencia de dicho objeto.
- Se modifica un valor del objeto observado.
- Cuando se produce un cambio en el objeto observado (se asigna un nuevo valor al atributo numero), en el mismo método setNumero() se llama al método notificarObservadores() implementado en la clase abstracta de la que hereda (la cual a su vez llama al método observadoActualizado() que implementan los objetos observadores, en el que cada uno de ellos se encargará de consultar al observado para comprobar los cambios producidos).

Para usar este patrón en Java podemos utilizar la clase abstracta Observable y la interface Observer que se encuentran ya implementadas.

El patrón de diseño Observer es parecido al patrón Mediator, si bien en él una clase central encapsula y dirige la comunicación generada entre los demás objetos.