El libro del Dr. Yan Hong "JAVA and Patterns" comienza con una descripción del patrón Mediador:
El patrón mediador es el patrón de comportamiento de los objetos. El patrón Mediator resume la forma en que interactúa un conjunto de objetos para que no tengan que hacer referencia explícita entre sí. Esto les permite acoplarse libremente. Cuando las interacciones entre algunos de estos objetos cambian, no afecta inmediatamente las interacciones entre otros objetos. Esto asegura que estas interacciones puedan variar independientemente unas de otras.
Por qué se necesita un mediador
Como se muestra en la figura siguiente, hay una gran cantidad de objetos en este diagrama esquemático. Estos objetos pueden afectar a otros objetos y verse afectados por otros objetos, por lo que a menudo se les denomina objetos colegas. Estos compañeros de trabajo forman el comportamiento del sistema a través de su interacción entre sí. Como se puede ver en la figura, casi todos los objetos necesitan interactuar con otros objetos, y esta interacción se manifiesta como un acoplamiento directo entre un objeto y otro objeto. Este es un sistema sobreacoplado.
Al introducir el objeto mediador (Mediador), la estructura de red del sistema se puede transformar en una estructura en estrella centrada en el mediador, como se muestra en la siguiente figura. En esta estructura en estrella, un objeto colega ya no interactúa con otro objeto a través de una conexión directa, sino que interactúa con otro objeto a través de un objeto mediador. La existencia del objeto mediador garantiza la estabilidad de la estructura del objeto, es decir, la estructura del sistema no causará mucho trabajo de modificación debido a la introducción de nuevos objetos.
Un buen diseño orientado a objetos puede aumentar la colaboración y reducir el acoplamiento entre objetos. Un diseño bien pensado divide un sistema en un grupo de objetos de compañeros de trabajo que cooperan, luego otorga a cada objeto de compañeros de trabajo responsabilidades únicas y configura apropiadamente las relaciones de colaboración entre ellos para que puedan trabajar juntos.
Si no hay placa base
Como todos sabemos, la interacción entre varios accesorios de la computadora se completa principalmente a través de la placa base. Si no hay una placa base en la computadora, entonces los distintos accesorios deben interactuar entre sí para transmitir datos entre sí. Y debido a que las interfaces de cada accesorio son diferentes, al interactuar entre sí, la interfaz de datos debe convertirse para que coincida.
Afortunadamente, con la placa base, la interacción de varios accesorios se completa completamente a través de la placa base. Cada accesorio solo necesita interactuar con la placa base, y la placa base sabe cómo lidiar con todos los accesorios, lo que lo hace mucho más simple.
La estructura del patrón mediador.
A continuación se muestra un diagrama de clases esquemático para el patrón Mediador:
El modo mediador incluye los siguientes roles:
● Rol de mediador abstracto (Mediador): define la interfaz del objeto colega al objeto mediador, en la que el método principal es uno (o más) métodos de evento.
● Rol de Mediador concreto (ConcreteMediator): implementa el método de evento declarado por el mediador abstracto. El mediador específico conoce todas las clases de colegas específicas y es responsable de coordinar específicamente la interacción entre cada objeto de colega.
● Rol de clase de colega abstracto (Colega): define la interfaz del mediador al objeto colega. Los objetos colega sólo conocen al mediador y no a los demás objetos colegiados.
● Rol ConcreteColleague: todas las clases de colegas concretas heredan de la clase de colegas abstracta. Para implementar su propio negocio, cuando necesite comunicarse con otros colegas, comuníquese con el mediador que lo desempeña. El mediador será el responsable de interactuar con los demás colegas.
código fuente
El código de copia de la clase mediadora abstracta es el siguiente:
Mediador de interfaz pública {
/**
* El objeto colega notifica al método mediador cuando cambia.
* Deje que el mediador sea responsable de las interacciones correspondientes con otros objetos colegas.
*/
vacío público cambiado (colega c);
}
clase mediadora concreta
Copie el código de código de la siguiente manera:
clase pública ConcreteMediator implementa Mediador {
//Retener y mantener al colega A
privado ConcreteColleagueA colegaA;
//Retener y mantener al colega B
privado ConcreteColleagueB colegaB;
public void setColleagueA(ConcreteColleagueA colegaA) {
this.colegaA = colegaA;
}
public void setColleagueB(ConcreteColleagueB colegaB) {
this.colegaB = colegaB;
}
@Anular
vacío público cambiado (colega c) {
/**
* Una determinada clase de colega ha cambiado, lo que generalmente requiere interacción con otros colegas.
* Coordinar específicamente los objetos de colegas correspondientes para lograr un comportamiento colaborativo.
*/
}
}
clase de colega abstracta
Copie el código de código de la siguiente manera:
Colega de clase abstracta pública {
//Mantener un objeto mediador
mediador mediador privado;
/**
*Constructor
*/
Colega público(Mediador mediador){
this.mediador = mediador;
}
/**
* Obtener el objeto mediador correspondiente a la clase de colega actual
*/
Mediador público getMediator() {
mediador de retorno;
}
}
El código específico para copiar la misma clase es el siguiente:
clase pública ConcreteColleagueA extiende Colega {
public ConcreteColleagueA(Mediador mediador) {
super(mediador);
}
/**
* Indicar métodos para realizar determinadas operaciones.
*/
operación de anulación pública(){
//Notificar al objeto mediador cuando necesite comunicarse con otros colegas
getMediator().cambiado(esto);
}
}
Copie el código de código de la siguiente manera:
clase pública ConcreteColleagueB extiende Colega {
public ConcreteColleagueB(Mediador mediador) {
super(mediador);
}
/**
* Indicar métodos para realizar determinadas operaciones.
*/
operación de anulación pública(){
//Notificar al objeto mediador cuando necesite comunicarse con otros colegas
getMediator().cambiado(esto);
}
}
Usa tu computadora para ver películas
En la vida diaria, a menudo usamos computadoras para ver películas. Describamos este proceso. Después de la simplificación, asumimos que habrá el siguiente proceso interactivo:
(1) Primero, la unidad óptica debe leer los datos del disco óptico y luego informar a la placa base que su estado ha cambiado.
(2) La placa base obtiene los datos de la unidad óptica y los entrega a la CPU para su análisis y procesamiento.
(3) Una vez que la CPU termina de procesar, divide los datos en datos de video y datos de audio y notifica a la placa base que ha terminado de procesar.
(4) La placa base obtiene los datos procesados por la CPU y los pasa a la tarjeta gráfica y a la tarjeta de sonido respectivamente para mostrar el video y emitir sonidos.
Para implementar el ejemplo utilizando el patrón mediador, es necesario distinguir entre objetos colegas y objetos mediadores. Obviamente, la placa base es el mediador y los accesorios como unidades ópticas, tarjetas de sonido, CPU y tarjetas gráficas son todos colegas.
código fuente
El código de copia abstracto de la clase de colega es el siguiente:
Colega de clase abstracta pública {
//Mantener un objeto mediador
mediador mediador privado;
/**
*Constructor
*/
Colega público(Mediador mediador){
this.mediador = mediador;
}
/**
* Obtener el objeto mediador correspondiente a la clase de colega actual
*/
Mediador público getMediator() {
mediador de retorno;
}
}
Clase de colega: el código de copia de la unidad óptica es el siguiente:
CDDriver de clase pública extiende Colega {
//Datos leídos de la unidad óptica
datos de cadena privada = "";
/**
*Constructor
*/
CDDriver público (mediador mediador) {
super(mediador);
}
/**
* Obtener los datos leídos del disco.
*/
cadena pública getData() {
datos de devolución;
}
/**
* Leer CD
*/
lectura CD nula pública(){
//Antes de la coma están los datos que se muestran en el video y después de la coma está el sonido.
this.data = "One Piece, estoy decidido a ser el Rey Pirata";
//Notificar a la placa base que su estado ha cambiado
getMediator().cambiado(esto);
}
}
Clase de colega——CPU
Copie el código de código de la siguiente manera:
CPU de clase pública extiende Colega {
//Datos de vídeo descompuestos
cadena privada videoData = "";
//Datos de sonido descompuestos
cadena privada soundData = "";
/**
*Constructor
*/
CPU pública (mediador mediador) {
super(mediador);
}
/**
* Obtener datos de video descompuestos
*/
cadena pública getVideoData() {
devolver videoData;
}
/**
* Obtener los datos de sonido descompuestos
*/
cadena pública getSoundData() {
devolver datos de sonido;
}
/**
* Procesar los datos y dividirlos en datos de audio y video.
*/
ejecutar datos vacíos públicos (datos de cadena) {
// Descomponer los datos. El frente son datos de video y el reverso son datos de audio.
Cadena[] matriz = data.split(",");
this.videoData = matriz[0];
this.soundData = matriz[1];
//Notifica a la placa base que la CPU ha completado el trabajo
getMediator().cambiado(esto);
}
}
Clase de colega: el código de copia de la tarjeta gráfica es el siguiente:
VideoCard de clase pública extiende Colega {
/**
*Constructor
*/
Tarjeta de video pública (mediador mediador) {
super(mediador);
}
/**
* Mostrar datos de vídeo
*/
showData público vacío (datos de cadena) {
System.out.println("Estás viendo: " + datos);
}
}
Clase de colega: el código de copia de la tarjeta de sonido es el siguiente:
SoundCard de clase pública extiende Colega {
/**
*Constructor
*/
tarjeta de sonido pública (mediador mediador) {
super(mediador);
}
/**
* Hacer sonidos basados en datos de audio
*/
datos de sonido públicos vacíos (datos de cadena) {
System.out.println("Voz en off: " + datos);
}
}
El código de copia de la clase mediadora abstracta es el siguiente:
Mediador de interfaz pública {
/**
* El objeto colega notifica al método mediador cuando cambia.
* Deje que el mediador sea responsable de las interacciones correspondientes con otros objetos colegas.
*/
vacío público cambiado (colega c);
}
El código de copia de la clase mediadora específica es el siguiente:
MainBoard de clase pública implementa Mediador {
//Necesitamos conocer la clase de colega con la que interactuar: la clase de unidad óptica
CDDriver privado cdDriver = nulo;
//Necesitamos conocer la clase de colega con la que interactuar: clase de CPU
CPU privada CPU = nula;
//Necesitamos conocer la clase de colegas con los que interactuar: la clase de tarjeta gráfica
tarjeta de video privada tarjeta de video = nula;
//Necesitamos conocer la clase de colegas con los que interactuar: la clase de tarjeta de sonido
tarjeta de sonido privada tarjeta de sonido = nula;
setCdDriver vacío público (CDDriver cdDriver) {
this.cdDriver = cdDriver;
}
setCpu público vacío (CPU) {
esto.cpu = cpu;
}
setVideoCard público vacío (tarjeta de video tarjeta de video) {
this.videoCard = videoCard;
}
setSoundCard público vacío (Tarjeta de sonido tarjeta de sonido) {
this.soundCard = tarjeta de sonido;
}
@Anular
vacío público cambiado (colega c) {
si (c instancia de CDDriver) {
//Indica que la unidad óptica ha leído datos
this.opeCDDriverReadData((CDDriver)c);
}si no (c instancia de CPU){
this.opeCPU((CPU)c);
}
}
/**
* Manejar la interacción con otros objetos después de que la unidad óptica lee datos
*/
opeCDDriverReadData vacío privado (CDDriver cd) {
//Primero obtenga los datos leídos por la unidad óptica
Datos de cadena = cd.getData();
//Transfiere estos datos a la CPU para su procesamiento
cpu.executeData(datos);
}
/**
* Manejar la interacción entre la CPU y otros objetos después de procesar los datos.
*/
opeCPU privado vacío(CPU cpu){
// Primero obtiene los datos procesados por la CPU
Cadena videoData = cpu.getVideoData();
Cadena soundData = cpu.getSoundData();
//Transfiere estos datos a la tarjeta gráfica y a la tarjeta de sonido para su visualización
videoCard.showData(videoData);
tarjeta de sonido.datos de sonido(datos de sonido);
}
}
El código de copia de la clase de cliente es el siguiente:
Cliente de clase pública {
público estático vacío principal (String [] argumentos) {
//Crear mediador - placa base
Mediador de MainBoard = nuevo MainBoard();
//Crear clase de colega
CDDriver cd = nuevo CDDriver(mediador);
CPU CPU = nueva CPU (mediador);
VideoCard vc = nueva VideoCard(mediador);
SoundCard sc = nueva SoundCard(mediador);
//Informar al mediador a todos los colegas
mediador.setCdDriver(cd);
mediador.setCpu(cpu);
mediador.setVideoCard(vc);
mediador.setSoundCard(sc);
//Comienza a ver la película, coloca el disco en la unidad óptica y la unidad óptica comienza a leer el disco.
cd.readCD();
}
}
Los resultados de ejecución son los siguientes:
Ventajas del patrón mediador
● acoplamiento flojo
El patrón mediador encapsula las interacciones entre múltiples objetos colegas en el objeto mediador, acoplando así de manera flexible los objetos colegas y básicamente logrando dependencias complementarias. De esta manera, los objetos de los compañeros se pueden cambiar y reutilizar de forma independiente, en lugar de "mover un lugar y afectar a todo el cuerpo" como antes.
● Control centralizado de las interacciones.
Las interacciones de múltiples objetos de colegas se encapsulan en el objeto mediador para una administración centralizada, de modo que cuando estos comportamientos interactivos cambian, solo necesita modificar el objeto mediador. Por supuesto, si es un sistema ya completo, luego expanda el objeto mediador. y no es necesario modificar cada clase de colega.
● Muchos a muchos se convierten en uno a muchos
Cuando no se utiliza el patrón mediador, la relación entre los objetos colega suele ser de muchos a muchos. Después de introducir el objeto mediador, la relación entre el objeto mediador y el objeto colega suele convertirse en una relación bidireccional de uno a muchos. lo que hace que la relación entre los objetos sea más fácil de entender e implementar.
Desventajas del patrón mediador
Un posible inconveniente del modelo mediador es la excesiva centralización. Si la interacción de los objetos colegas es muy grande y compleja, cuando todas estas complejidades se concentran en el mediador, el objeto mediador se volverá muy complejo y difícil de gestionar y mantener.