oop - los - Mediator Vs Observer Patrones de diseño orientados a objetos
patrones de diseño java (7)
He estado leyendo la Banda de los Cuatro , para resolver algunos de mis problemas y encontré el patrón del Mediador .
Anteriormente había usado Observer en mis proyectos para hacer alguna aplicación GUI. Estoy un poco confundido ya que no encuentro una gran diferencia entre los dos. Busqué para encontrar la diferencia, pero no pude encontrar ninguna respuesta apta para mi consulta.
¿Podría alguien ayudarme a diferenciar entre los dos con algún buen ejemplo que delimite claramente los dos?
Observador
1. Sin
Cliente1 : Oye Asunto , ¿cuándo cambias?
Cliente2 : ¿Cuándo cambiaste el asunto ? ¡No me he dado cuenta!
Cliente3 : Sé que el sujeto ha cambiado.
2. Con
- Los clientes están en silencio.
- Algún tiempo después ...
- Asunto : Estimados clientes , ¡he cambiado!
Mediador
1. Sin
- Cliente1 : Hey Taxi1 , llévame a algún lado.
- Client2 : Hey Taxi1 , llévame a algún lado.
- Cliente1 : Hey Taxi2 , llévame a algún lado.
- Client2 : Hey Taxi2 , llévame a algún lado.
2. Con
- Cliente1 : Hey TaxiCenter , por favor llévame un Taxi .
- Cliente2 : Hey TaxiCenter , por favor llévame un Taxi .
@cdc explicó la diferencia en la intención de manera excelente.
Añadiré más información al principio.
Observer : permite la notificación de un evento en un objeto a un conjunto diferente de objetos (instancias de diferentes clases)
Mediator : centralice la comunicación entre el conjunto de objetos, creado a partir de una clase particular.
Estructura del patrón de mediador de dofactory :
Mediador : define una interfaz para la comunicación entre colegas.
Colega : es una clase abstracta, que define los eventos que se comunicarán entre colegas
ConcreteMediator : implementa el comportamiento cooperativo mediante la coordinación de los objetos del colega y mantiene a sus colegas
ConcreteColleague : implementa las operaciones de notificación recibidas a través de Mediator , que ha sido generado por otro colega
Un ejemplo del mundo real:
Mantiene una red de computadoras en la topología de malla . Si se agrega una computadora nueva o se elimina la computadora existente, todas las otras computadoras en esa red deben conocer estos dos eventos.
Veamos cómo se adapta el patrón del Mediador.
Fragmento de código:
import java.util.List;
import java.util.ArrayList;
/* Define the contract for communication between Colleagues.
Implementation is left to ConcreteMediator */
interface Mediator{
public void register(Colleague colleague);
public void unregister(Colleague colleague);
}
/* Define the contract for notification events from Mediator.
Implementation is left to ConcreteColleague
*/
abstract class Colleague{
private Mediator mediator;
private String name;
public Colleague(Mediator mediator,String name){
this.mediator = mediator;
this.name = name;
}
public String toString(){
return name;
}
public abstract void receiveRegisterNotification(Colleague colleague);
public abstract void receiveUnRegisterNotification(Colleague colleague);
}
/* Process notification event raised by other Colleague through Mediator.
*/
class ComputerColleague extends Colleague {
private Mediator mediator;
public ComputerColleague(Mediator mediator,String name){
super(mediator,name);
}
public void receiveRegisterNotification(Colleague colleague){
System.out.println("New Computer register event with name:"+colleague+
": received @"+this);
// Send further messages to this new Colleague from now onwards
}
public void receiveUnRegisterNotification(Colleague colleague){
System.out.println("Computer left unregister event with name:"+colleague+
":received @"+this);
// Do not send further messages to this Colleague from now onwards
}
}
/* Act as a central hub for communication between different Colleagues.
Notifies all Concrete Colleagues on occurrence of an event
*/
class NetworkMediator implements Mediator{
List<Colleague> colleagues = new ArrayList<Colleague>();
public NetworkMediator(){
}
public void register(Colleague colleague){
colleagues.add(colleague);
for (Colleague other : colleagues){
if ( other != colleague){
other.receiveRegisterNotification(colleague);
}
}
}
public void unregister(Colleague colleague){
colleagues.remove(colleague);
for (Colleague other : colleagues){
other.receiveUnRegisterNotification(colleague);
}
}
}
public class MediatorPatternDemo{
public static void main(String args[]){
Mediator mediator = new NetworkMediator();
ComputerColleague colleague1 = new ComputerColleague(mediator,"Eagle");
ComputerColleague colleague2 = new ComputerColleague(mediator,"Ostrich");
ComputerColleague colleague3 = new ComputerColleague(mediator,"Penguin");
mediator.register(colleague1);
mediator.register(colleague2);
mediator.register(colleague3);
mediator.unregister(colleague1);
}
}
salida:
New Computer register event with name:Ostrich: received @Eagle
New Computer register event with name:Penguin: received @Eagle
New Computer register event with name:Penguin: received @Ostrich
Computer left unregister event with name:Eagle:received @Ostrich
Computer left unregister event with name:Eagle:received @Penguin
Explicación:
- Eagle se agrega a la red al principio a través del evento de registro. No hay notificaciones a otros colegas, ya que Eagle es el primero.
- Cuando se agrega avestruz a la red, se notifica a Eagle : la línea 1 de salida se representa ahora.
- Cuando Penguin se agrega a la red, tanto Eagle como Ostrich han sido notificados: la línea 2 y la línea 3 de salida se procesan ahora.
- Cuando Eagle abandonó la red a través del evento de anulación del registro, se notificó a Ostrich y Penguin . La línea 4 y la línea 5 de salida se representan ahora.
Acerca de esta explicación Técnicamente, tanto Observer como Mediator son los mismos y se utilizan para proporcionar una forma desacoplada para la comunicación de componentes, pero el uso es diferente.
Mientras obeserver
notifica a los componentes suscritos sobre los cambios de estado (creación de un nuevo registro db, por ejemplo), el mediator
ordena a los componentes registrados hacer algo relacionado con el flujo lógico comercial (enviando un correo electrónico al usuario para restablecer la contraseña).
Observador
- Los consumidores de notificaciones son responsables de suscribirse para recibir notificaciones
- El procesamiento de notificación no es parte del flujo comercial
Mediador
- Se requiere un registro explícito para conectar "editor" y "consumidores"
- El procesamiento de notificación es parte del flujo comercial específico
Aunque ambos se utilizan de manera organizada para hablar sobre los cambios de estado, son ligeramente diferentes desde el punto de vista estructural y semántico.
Observer se usa para transmitir un cambio de estado de un objeto particular, desde el objeto mismo. Entonces el cambio ocurre en el objeto central que también es responsable de señalarlo. Sin embargo, en Mediator, el cambio de estado puede ocurrir en cualquier objeto, pero se transmite desde un mediador. Entonces hay una diferencia en el flujo. Pero, no creo que esto afecte el comportamiento de nuestro código. Podemos usar uno u otro para lograr el mismo comportamiento. Por otro lado, esta diferencia podría tener algunos efectos en la comprensión conceptual del código.
Ver, el propósito principal de los patrones es más bien crear un lenguaje común entre los desarrolladores. Entonces, cuando veo un mediador, personalmente entiendo los múltiples elementos que intentan comunicarse a través de un solo intermediario / concentrador para reducir el ruido de comunicación (o para promover SRP) y cada objeto es igualmente importante en términos de tener la capacidad de señalar un cambio de estado. Por ejemplo, piense en varias aeronaves que se aproximan a un aeropuerto. Cada uno debe comunicarse sobre el pilón (mediador) en lugar de comunicarse entre sí. (Piense en 1000 aeronaves que se comunican entre sí al aterrizar)
Sin embargo, cuando veo un observador, significa que hay algunos cambios de estado que me pueden importar y que debo registrar / suscribir para escuchar los cambios de estado particulares. Hay un objeto central responsable de señalar los cambios de estado. Por ejemplo, si me importa un aeropuerto específico en mi camino de A a B, puedo registrarme en ese aeropuerto para ver algunos eventos transmitidos como si hubiera una pista vacía o algo así.
Espero que esté claro.
El patrón Observer: define una dependencia de uno a muchos entre los objetos para que cuando un objeto cambie de estado, todos sus dependientes sean notificados y actualizados automáticamente.
El patrón Mediator: define un objeto que encapsula cómo interactúan un conjunto de objetos. El mediador promueve el acoplamiento flexible evitando que los objetos se refieran entre sí de forma explícita, y le permite variar su interacción de forma independiente.
Fuente: dofactory
Ejemplo:
El patrón de observador: Clase A, puede tener cero o más observadores de tipo O registrados con él. Cuando algo en A cambia, notifica a todos los observadores.
El patrón del mediador: tiene un número de instancias de clase X (o tal vez incluso varios tipos diferentes: X, Y y Z), y desean comunicarse entre sí (pero no desea que cada uno tenga referencias explícitas a cada uno). otro), entonces usted crea una clase mediadora M. Cada instancia de X tiene una referencia a una instancia compartida de M, a través de la cual puede comunicarse con las otras instancias de X (o X, Y y Z).
En el libro original que acuñó los términos Observer y Mediator, Design Patterns, Elements of Reusable Object-Oriented Software , dice que el patrón de Mediator se puede implementar utilizando el patrón de observador. Sin embargo, también se puede implementar haciendo que los colegas (que son más o menos equivalentes al patrón de los sujetos del observador) tengan una referencia a una clase de mediador o a una interfaz de mediador.
Hay muchos casos en los que desearía usar el patrón del observador, su clave es que un objeto no debería saber qué otros objetos están observando su estado.
Mediator es un poco más específico, evita que las clases se comuniquen directamente, sino a través de un mediador. Esto ayuda al principio de responsabilidad única al permitir que la comunicación se descargue a una clase que solo maneja la comunicación.
Un ejemplo clásico de Mediator se encuentra en una GUI, donde el enfoque ingenuo podría llevar al código en un evento de clic de botón que dice "si el panel Foo está deshabilitado y el panel Bar tiene una etiqueta que dice" Ingrese la fecha ", entonces no llame al servidor, de lo contrario seguir adelante ", donde con el patrón de Mediator podría decir" solo soy un botón y no tengo ningún negocio en la tierra sabiendo sobre el panel Foo y la etiqueta en el panel de Bar, así que le preguntaré a mi mediador si llama al servidor está bien ahora ".
O bien, si Mediator se implementa con el patrón Observer, el botón debería decir "Hola, observadores (lo que incluiría al mediador), mi estado cambió (alguien me hizo clic). Haga algo al respecto si le importa". En mi ejemplo, probablemente tenga menos sentido que referenciar directamente al mediador, pero en muchos casos usar el patrón Observer para implementar Mediator tendría sentido, y la diferencia entre Observer y Mediator sería más una intención que una diferencia en el código mismo.
Estos patrones se utilizan en diferentes situaciones:
El patrón del mediador se usa cuando tiene dos subsistemas con alguna dependencia y uno de ellos se debe a un cambio, y dado que es posible que no desee cambiar el sistema que depende del otro, es posible que desee introducir un mediador que lo haga. desacoplar la dependencia entre ellos. De esta forma, cuando uno de los subsistemas cambia, todo lo que tiene que hacer es actualizar el mediador.
El patrón de observador se usa cuando una clase quiere permitir que otras clases se registren y recibir notificaciones sobre eventos, por ejemplo ButtonListener, etc.
Ambos patrones permiten un acoplamiento menor, pero son bastante diferentes.