Padrão de Design Mediator em Java

O padrão de design Mediator é um dos padrões de design comportamentais, portanto, lida com os comportamentos dos objetos. O padrão de design Mediator é usado para fornecer um meio de comunicação centralizado entre diferentes objetos em um sistema.

Padrão de Design Mediator

De acordo com o GoF, o objetivo do padrão de mediador é:

Permite um acoplamento flexível encapsulando a maneira como conjuntos díspares de objetos interagem e se comunicam entre si. Permite que as ações de cada conjunto de objetos variem independentemente umas das outras.

O padrão de design Mediator é muito útil em uma aplicação empresarial onde múltiplos objetos estão interagindo entre si. Se os objetos interagem diretamente entre si, os componentes do sistema estão fortemente acoplados, o que torna o custo de manutenção mais elevado e não é difícil de estender. O padrão Mediator foca em fornecer um mediador entre objetos para comunicação e ajuda na implementação de desacoplamento entre objetos. Um controlador de tráfego aéreo é um ótimo exemplo de padrão Mediator, onde a sala de controle do aeroporto funciona como um mediador para comunicação entre diferentes voos. O mediador atua como um roteador entre objetos e pode ter sua própria lógica para fornecer o modo de comunicação. Os objetos do sistema que se comunicam entre si são chamados de Colegas. Normalmente, temos uma interface ou classe abstrata que fornece o contrato para comunicação e, em seguida, temos a implementação concreta de mediadores. Para o nosso exemplo, vamos tentar implementar um aplicativo de chat onde os usuários podem participar de um chat em grupo. Cada usuário será identificado pelo seu nome e eles podem enviar e receber mensagens. A mensagem enviada por qualquer usuário deve ser recebida por todos os outros usuários do grupo.

Interface do Padrão Mediator

Primeiro, vamos criar uma interface Mediator que irá definir o contrato para mediadores concretos. ChatMediator.java

package com.journaldev.design.mediator;

public interface ChatMediator {

	public void sendMessage(String msg, User user);

	void addUser(User user);
}

Interface do Colega do Padrão Mediador

Os usuários podem enviar e receber mensagens, então podemos ter uma interface de Usuário ou uma classe abstrata. Estou criando o Usuário como uma classe abstrata como abaixo. User.java

package com.journaldev.design.mediator;

public abstract class User {
	protected ChatMediator mediator;
	protected String name;
	
	public User(ChatMediator med, String name){
		this.mediator=med;
		this.name=name;
	}
	
	public abstract void send(String msg);
	
	public abstract void receive(String msg);
}

Observe que o Usuário tem uma referência ao objeto mediador, é necessário para a comunicação entre diferentes usuários.

Mediador Concreto

Agora vamos criar a classe mediadora concreta, ela terá uma lista de usuários no grupo e fornecerá a lógica para a comunicação entre os usuários. ChatMediatorImpl.java

package com.journaldev.design.mediator;

import java.util.ArrayList;
import java.util.List;

public class ChatMediatorImpl implements ChatMediator {

	private List users;
	
	public ChatMediatorImpl(){
		this.users=new ArrayList<>();
	}
	
	@Override
	public void addUser(User user){
		this.users.add(user);
	}
	
	@Override
	public void sendMessage(String msg, User user) {
		for(User u : this.users){
			//a mensagem não deve ser recebida pelo usuário que a enviou
			if(u != user){
				u.receive(msg);
			}
		}
	}

}

Colaborador Concreto do Padrão de Projeto Mediador

Agora podemos criar classes de Usuário concretas para serem usadas pelo sistema cliente. UserImpl.java

package com.journaldev.design.mediator;

public class UserImpl extends User {

	public UserImpl(ChatMediator med, String name) {
		super(med, name);
	}

	@Override
	public void send(String msg){
		System.out.println(this.name+": Sending Message="+msg);
		mediator.sendMessage(msg, this);
	}
	@Override
	public void receive(String msg) {
		System.out.println(this.name+": Received Message:"+msg);
	}

}

Observe que o método send() está usando o mediador para enviar a mensagem aos usuários e não tem ideia de como ela será tratada pelo mediador.

Exemplo de Código do Programa Cliente do Padrão Mediator

Vamos testar nossa aplicação de chat com um programa simples onde iremos criar um mediador e adicionar usuários ao grupo, e um dos usuários enviará uma mensagem. ChatClient.java

package com.journaldev.design.mediator;

public class ChatClient {

	public static void main(String[] args) {
		ChatMediator mediator = new ChatMediatorImpl();
		User user1 = new UserImpl(mediator, "Pankaj");
		User user2 = new UserImpl(mediator, "Lisa");
		User user3 = new UserImpl(mediator, "Saurabh");
		User user4 = new UserImpl(mediator, "David");
		mediator.addUser(user1);
		mediator.addUser(user2);
		mediator.addUser(user3);
		mediator.addUser(user4);
		
		user1.send("Hi All");
		
	}

}

Observe que o programa cliente é muito simples e não tem ideia de como a mensagem está sendo manipulada e se o mediador está obtendo o usuário ou não. A saída do exemplo de programa do padrão Mediator é:

Pankaj: Sending Message=Hi All
Lisa: Received Message:Hi All
Saurabh: Received Message:Hi All
David: Received Message:Hi All

Diagrama de Classe do Padrão Mediator

Exemplo do Padrão Mediator no JDK

Pontos Importantes do Padrão de Projeto Mediator

  • O padrão Mediator é útil quando a lógica de comunicação entre objetos é complexa, podemos ter um ponto central de comunicação que cuida da lógica de comunicação.
  • O Serviço de Mensagens Java (JMS) utiliza o padrão Mediator juntamente com o padrão Observer para permitir que aplicações se inscrevam e publiquem dados para outras aplicações.
  • Não devemos usar o padrão Mediator apenas para alcançar um desacoplamento, pois se o número de mediadores aumentar, será difícil mantê-los.

Isso é tudo para o padrão de projeto Mediator e sua implementação em Java.

Source:
https://www.digitalocean.com/community/tutorials/mediator-design-pattern-java