PATRON OBSERVER

Motivacion:
En una aplicación donde se tiene una interfaz mostrando los cambios de un modelo interno del dominio del problema existe cierto nivel de acoplamiento entre las clases de interfaz y las del dominio. Mediante este patrón se busca que estas clases estén solo acopladas mediante una interfaz abstracta, la cual notificará  automáticamente cualquier estado de cambios, por lo general, llamando uno de sus métodos. Se utiliza principalmente para aplicar sistemas de manejo de evento distribuido.
Estructura:
Participantes:

Subjet:

Esta clase abstracta proporciona una interfaz para conectar y desconectar los observadores. Sin perjuicio de clase también tiene una lista de observadores. Contiene los métodos:

  • Attach- Agrega un nuevo observador de la lista de observadores de observación de la materia.
  • Detach- Elimina un observador de la lista de observadores de observación de la materia
  • Notify - Notifica cada observador llamando a la función de actualización en el observador, cuando se produce un cambio.

La función Attach tiene un argumento como observador. Esto puede ser una función virtual de la clase de observador (actualización en esta descripción), o un puntero de función (en general una función de objeto o functor) en un establecimiento no orientado a objetos.

ConcreteSubject

La clase proporciona el estado de interés para los observadores. También envía una notificación a todos los observadores, llamando a la función de notificar en su superclase o clase base (es decir, en la reserva de la clase). Contiene esta función:

  • GetState - Regresa el estado de la materia.

Observadores

Esta clase define una interfaz de actualización para todos los observadores, para recibir notificación de actualización de la materia. Observadores de la clase se utiliza como una clase abstracta para la aplicación concreta de observadores. Contiene esta función:

  • Update - Una función abstracta, que será anulada por los observadores  concretos.

ConcreteObserver

Esta clase mantiene una referencia con la ConcreteSubject, para recibir el estado de la cuestión cuando se recibe una notificación. Contiene esta función:

  • Update - Esta es la función de anular en la clase concreta. Cuando esta función es llamada por el tema, el ConcreteObserver llama a la función de GetState el tema para actualizar la información que tiene sobre el estado del sujeto.

Cada observador concreto se aplica la función de actualización y, en consecuencia, define su propio comportamiento se produce cuando la notificación.

Cuando se produce un cambio  de materia, envía una notificación a todos los observadores, llamando a la función  Notify . Llama a la función de Update de todos los sujetos  de observadores. Notificar a la actualización y funciones pueden tener parámetros que indican el tipo de cambio se ha producido con el tema. Esto permite la optimización en el observador (sólo la actualización de las partes que cambiaron).

Implementacion:

El siguiente ejemplo, simula un chat, donde el servidor u observador en éste caso envía mensajes a sus clientes u observados conectados, puede crear más observados y a la vez activalos y desactivarlos.

package logica;

import java.util.ArrayList;

public class Observador {

    private int i;

    private String infor="";

    protected String mensaje = "";

    private ArrayList observador  =new ArrayList();

    public void notificar() {

        i = observador.size();

        for (int x = 0; x <>

            if (observador.get(x).getEstado() == true) {

                observador.get(x).notificar(mensaje);

            }

        }

    }

    public int getSize() {

        return observador.size();

    }

    public void setMensaje(String str) {

        mensaje=str;

    }

    public String getMensaje(){

        infor="";

        int y;

        for (int x = 0; x <>

            y=x+1;

            infor=infor+"Observador #: "+y+" - "+observador.get(x).getInformacion()+"\n";

        }

        return infor;

    }

    public void agregarObservado() {

        observador.add(new Observados());

    }

    public void desactivarObservado(int ob) {

        observador.get(ob).desactivarestado();

    }

    public void activarObservador(int ob) {

        observador.get(ob).activarEstado();

    }

}

package logica;
/**
 *
 * @author Katherin
 */
public class Observados extends Observador {
    private boolean estado;
    public Observados(){
        estado = true;
        mensaje="Conectado...";
    }
    public void notificar(String info) {
        mensaje = info;
    }
    public void activarEstado() {
        estado = true;
        mensaje="Conectado nuevamente...";
    }
    public void desactivarestado() {
        estado = false;
        mensaje="Desconectado....";
    }
    public boolean getEstado() {
        return estado;
    }
    public String  getInformacion() {
        return mensaje;
    }
}
package imobserver;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;
import logica.Observador;
public class Mensajes extends JFrame implements ActionListener {
    private JTextArea tablero;
    private String text = "";
    private String texto = "";
    private JButton cambiarColorTexto;
    private JButton nuevoObservado;
    private JButton desactivarObservado;
    private JButton activarObservado;
    private JButton notificar;
    private int tam = 15;
    private Font f;
    private int ob;
    private Observador observador;
    public Mensajes() {
        this.setLayout(null);
        this.setTitle("Observer");
        this.setSize(400, 500);
        this.setLocation(100, 100);
        observador = new Observador();
        f = new Font("Helvetica", Font.ITALIC + Font.BOLD, tam);
        tablero = new JTextArea();
        tablero.setSize(350, 300);
        tablero.setLocation(10, 10);
        tablero.setFont(f);
        tablero.setText("");
        tablero.setEditable(false);
        add(tablero);
        JScrollPane areaScrollPane = new JScrollPane(tablero);
        areaScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        areaScrollPane.setSize(350, 300);
        areaScrollPane.setLocation(10, 10);
        this.getContentPane().add(areaScrollPane);
        desactivarObservado = new JButton();
        desactivarObservado.setSize(300, 20);
        desactivarObservado.setLocation(40, 390);
        desactivarObservado.setText("Desactivar Observado");
        desactivarObservado.addActionListener(this);
        add(desactivarObservado);
        nuevoObservado = new JButton();
        nuevoObservado.setSize(300, 20);
        nuevoObservado.setLocation(40, 360);
        nuevoObservado.setText("Nuevo  Observado");
        nuevoObservado.addActionListener(this);
        add(nuevoObservado);
        activarObservado = new JButton();
        activarObservado.setSize(300, 20);
        activarObservado.setLocation(40, 330);
        activarObservado.setText("Activar Observado");
        activarObservado.addActionListener(this);
        add(activarObservado);
        notificar = new JButton();
        notificar.setSize(300, 20);
        notificar.setLocation(40, 420);
        notificar.setText("Notificar mensaje");
        notificar.addActionListener(this);
        add(notificar);
        addWindowListener(new Cierre());
    }
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == nuevoObservado) {
            observador.agregarObservado();
        }
        if (e.getSource() == desactivarObservado) {
            ob=Integer.decode(JOptionPane.showInputDialog(null,"Numero del observado"))-1;
            if (ob <>
                observador.desactivarObservado(ob);
            } else {
                JOptionPane.showMessageDialog(null, "No existe observado: " + tam);
            }
        }
        if (e.getSource() == activarObservado) {
             ob=Integer.decode(JOptionPane.showInputDialog(null, "Numero del observado"))-1;
            if (ob <>
                observador.activarObservador(ob);
            } else {
                JOptionPane.showMessageDialog(null, "No existe observado: " + tam);
            }
        }
        if (e.getSource() == notificar) {
            text = JOptionPane.showInputDialog("mensaje a notificar a los Observados");
            if (text != null) {
                observador.setMensaje(text);
                observador.notificar();
            }
        }
        tablero.setText(observador.getMensaje());
    }
    class Cierre extends WindowAdapter {
        @Override
        public void windowClosing(WindowEvent e) {
            System.exit(0);
        }
    }
}
package imobserver;
/**
 *
 * @author Katherin
 */
public class Main {
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Mensajes ventana=new Mensajes();
        ventana.setVisible(true);
    }
}

Referencias:

1 comentario:

  1. Podrias terminar el codigo??
    Faltan los for, los if y da un par de fallos.
    O si me lo puedes explicar, es que tengo que hacer uno igual....
    Gracias!!

    ResponderEliminar