El patrón de observador es un patrón de diseño de comportamiento. El uso del patrón Observer es cuando está interesado en el estado de un objeto y desea recibir una notificación cada vez que cambia. En el patrón de observador, el objeto que observa el estado de otro objeto se llama Observador y el objeto observado se llama Sujeto. Según las reglas de GoF, la intención del patrón Observer es:
Copie el código de código de la siguiente manera:
Defina una relación de dependencia de uno a muchos entre objetos. Si el estado de un objeto cambia, otros objetos relacionados serán notificados y actualizados automáticamente.
Los sujetos contienen observadores que deben ser notificados cuando cambia su estado. Por lo tanto, debería proporcionar a los observadores métodos para registrarse y cancelar el registro. Cuando el Asunto (observado) cambia, también debe incluir un método para notificar a todos los observadores. Al notificar a los observadores, puede enviar actualizaciones o proporcionar otro método para obtener actualizaciones.
Los observadores deben tener un método que establezca el objeto observador y que el observador pueda utilizar para notificarle las actualizaciones.
JAVA proporciona formas integradas de implementar el patrón de observador, las interfaces java.util.Observable y java.util.Observer. Sin embargo, no son muy utilizados. Debido a que esta implementación es demasiado simple, la mayoría de las veces no queremos que la última clase extendida simplemente implemente el patrón de observador, porque las clases JAVA no pueden heredar varias veces.
El servicio de mensajes Java Messages Service (JMS) utiliza el modo observador y el modo comando para realizar la publicación y suscripción de datos entre diferentes programas.
El marco de control de vista-modelo de MVC también utiliza el patrón de observador, tratando el modelo como lo observado y la vista como el observador. Las vistas pueden registrarse en el modelo para recibir cambios en el modelo.
Ejemplo de patrón de observador
En este ejemplo, completaremos una discusión de tema simple y los observadores pueden registrarse para este tema. Cualquier cambio resultante del envío de contenido sobre este tema será notificado a todos los observadores registrados.
Según las necesidades de los observadores del Asunto, esto es implementar una interfaz de Asunto básica. Esta interfaz especifica una serie de métodos específicos que deben implementarse en la clase específica que implementa la interfaz posteriormente.
Copie el código de código de la siguiente manera:
paquete com.journaldev.design.observer;
interfaz pública Asunto {
//métodos para registrar y dar de baja observadores
registro público vacío (Observador obj);
anulación del registro público nulo (Observador obj);
//método para notificar a los observadores del cambio
notifyObservers públicos vacíos();
//método para obtener actualizaciones del tema
objeto público getUpdate (obj del observador);
}
Ahora crea un observador asociado. Necesita un método para adjuntar el Sujeto a un observador. Los métodos adicionales pueden aceptar notificaciones de cambio de asunto.
Copie el código de código de la siguiente manera:
paquete com.journaldev.design.observer;
interfaz pública Observador {
//método para actualizar el observador, utilizado por el sujeto
actualización pública nula();
//adjuntar con tema a observar
setSubject público vacío (Subsujeto);
}
Esta conexión ha sido establecida. Ahora implemente el tema concreto.
Copie el código de código de la siguiente manera:
paquete com.journaldev.design.observer;
importar java.util.ArrayList;
importar java.util.List;
clase pública MyTopic implementa Asunto {
observadores privados de Lista<Observador>;
mensaje de cadena privado;
booleano privado cambiado;
Objeto final privado MUTEX= nuevo Objeto();
Mi tema público(){
this.observers=new ArrayList<>();
}
@Anular
registro público vacío (Observador obj) {
if(obj == null) throw new NullPointerException("Null Observer");
if(!observadores.contiene(obj)) observadores.add(obj);
}
@Anular
anulación del registro público vacío (Observador obj) {
observadores.remove(obj);
}
@Anular
notifyObservers públicos vacíos() {
Lista<Observador> observadoresLocal = null;
//la sincronización se utiliza para garantizar que ningún observador registrado después de recibir el mensaje no sea notificado
sincronizado (MUTEX) {
si (! cambiado)
devolver;
observadoresLocal = new ArrayList<>(this.observers);
this.changed=false;
}
para (Observador obj: observadores locales) {
obj.actualización();
}
}
@Anular
objeto público getUpdate (obj del observador) {
devolver este mensaje;
}
//método para publicar un mensaje en el tema
postMessage público vacío (mensaje de cadena) {
System.out.println("Mensaje publicado en el tema:"+msg);
this.message=msg;
this.changed=true;
notificarObservadores();
}
}
La implementación de los métodos de observador de registro y cancelación del registro es muy simple. El cliente utilizará el método adicional postMessage() para enviar un mensaje de cadena a este tema. Tenga en cuenta que las variables booleanas se utilizan para rastrear cambios en el estado del tema y notificar a los observadores sobre dichos cambios. Esta variable es necesaria porque si no hay actualización, pero alguien llama al método notifyObservers(), no puede enviar información de notificación de error a los observadores.
Además, cabe señalar que la sincronización se utiliza en notifyObservers() para garantizar que las notificaciones solo se puedan enviar a observadores registrados antes de que el mensaje se publique en el tema.
Aquí está la implementación del observador. Siempre se centrarán en el objeto sujeto.
Copie el código de código de la siguiente manera:
paquete com.journaldev.design.observer;
clase pública MyTopicSubscriber implementa Observador {
nombre de cadena privada;
tema privado;
public MyTopicSubscriber(Cadena nm){
este.nombre=nm;
}
@Anular
actualización pública vacía () {
Mensaje de cadena = (Cadena) topic.getUpdate(this);
si(msj==nulo){
System.out.println(name+":: No hay mensaje nuevo");
}demás
System.out.println(nombre+":: Consumiendo mensaje::"+msg);
}
@Anular
setSubject público vacío (Subsujeto) {
este.tema=sub;
}
}
Tenga en cuenta que la implementación del método update() utiliza getUpdate() del observador para manejar mensajes actualizados. Aquí se debe evitar pasar el mensaje como parámetro al método update().
Aquí hay un programa de prueba simple para verificar la implementación de la clase de tema.
Copie el código de código de la siguiente manera:
paquete com.journaldev.design.observer;
clase pública ObserverPatternTest {
público estático vacío principal (String [] argumentos) {
//crear asunto
Tema MiTema = nuevo MiTema();
//crear observadores
Observador obj1 = new MyTopicSubscriber("Obj1");
Observador obj2 = new MyTopicSubscriber("Obj2");
Observador obj3 = new MyTopicSubscriber("Obj3");
//registrar observadores al sujeto
tema.register(obj1);
tema.register(obj2);
tema.register(obj3);
//adjuntar observador al sujeto
obj1.setSubject(tema);
obj2.setSubject(tema);
obj3.setSubject(tema);
//comprueba si hay alguna actualización disponible
obj1.actualización();
//ahora enviar mensaje al asunto
topic.postMessage("Nuevo mensaje");
}
}
Aquí está el resultado anterior:
Copie el código de código de la siguiente manera:
Obj1:: No hay mensaje nuevo
Mensaje publicado en el tema:Nuevo mensaje
Obj1::Mensaje de consumo::Nuevo mensaje
Obj2::Mensaje de consumo::Nuevo mensaje
Obj3::Mensaje consumidor::Nuevo mensaje</pre>
Diagrama UML del patrón Observer
El patrón de observador también se denomina patrón de publicación-suscripción. Algunas aplicaciones específicas en JAVA son las siguientes:
1.java.util.EventListener en Swing
2.javax.servlet.http.HttpSessionBindingListener
3.javax.servlet.http.HttpSessionAttributeListener
Los anteriores son todos modos de observador. Espero que ya os guste. Comparta sus sentimientos en los comentarios o compártalos con otros.