MTI TEK
  • Home
  • About
  • LLMs
  • Docker
  • Kubernetes
  • Java
  • All Resources
Java Design Patterns | Mediator
  1. Overview and Definition
  2. Class Diagram
  3. Implementation Example
    • The Mediator Interface
    • The Concrete Mediator
    • The Colleague Interface
    • The Colleague Classes
    • Testing the Mediator Pattern

  1. Overview and Definition
    The Mediator pattern is a behavioral design pattern that defines how a set of objects interact with each other. Instead of objects communicating directly, they communicate through a central mediator object. This promotes loose coupling by keeping objects from referring to each other explicitly.

    Key Components:
    • Mediator: Defines the interface for communication between colleague objects.
    • Concrete Mediator: Implements the mediator interface and coordinates communication between colleague objects.
    • Colleague: Defines the interface for objects that communicate through the mediator.
    • Concrete Colleague: Implements the colleague interface and communicates with other colleagues through the mediator.

    Benefits:
    • Loose Coupling: Reduces dependencies between communicating objects by having them refer only to the mediator.
    • Centralized Control: Encapsulates complex communications and control logic in one place.
    • Reusability: Individual colleague objects can be reused more easily since they don't depend on many other objects.
  2. Class Diagram
    Mediator Pattern Components:
    • Mediator: ServiceDiscovery interface - defines the communication interface for service discovery operations.
    • Concrete Mediator: ServiceDiscoveryMediator class - coordinates communication between clients and services in a microservices architecture.
    • Colleague Interface: Colleague interface - defines the common interface for all participants in the mediated communication.
    • Colleagues: Client and Service classes - communicate through the mediator instead of directly with each other.
    ┌─────────────────────────────────────────────┐
    │            <<interface>>                    │
    │           ServiceDiscovery                  │  ← Mediator
    ├─────────────────────────────────────────────┤
    │ + registerClient(Client): void              │
    │ + registerService(Service): void            │
    │ + discoverService(Client, String): void     │
    │ + notifyAvailability(Service, String): void │
    └─────────────────────────────────────────────┘
                 △
                 │ implements
                 │
    ┌─────────────────────────────────────────────┐
    │          ServiceDiscoveryMediator           │  ← Concrete Mediator
    ├─────────────────────────────────────────────┤
    │ - clients: List<Client>                     │
    │ - services: List<Service>                   │
    │ + registerClient(Client): void              │
    │ + registerService(Service): void            │
    │ + discoverService(Client, String): void     │
    │ + notifyAvailability(Service, String): void │
    └─────────────────────────────────────────────┘
    
    
    ┌───────────────────────────────────────┐
    │             <<interface>>             │
    │               Colleague               │  ← Colleague Interface
    ├───────────────────────────────────────┤
    │ + getId(): String                     │
    │ + setMediator(ServiceDiscovery): void │
    └───────────────────────────────────────┘
                 △
                 │ implements
                 │
    ┌──────────────────────────────┬──────────────────────────────────────────┐
    │            Client            │                 Service                  │  ← Concrete Colleagues
    ├──────────────────────────────┼──────────────────────────────────────────┤
    │ - id: String                 │ - id: String                             │
    │ - mediator: ServiceDiscovery │ - mediator: ServiceDiscovery             │
    │ + discoverService(String)    │ + notifyAvailability(String)             │
    │ + receiveServiceInfo()       │ + receiveDiscoveryRequest()              │
    └──────────────────────────────┴──────────────────────────────────────────┘
                   
  3. Implementation Example
    • The Mediator Interface:
      The Mediator interface defines the contract for service discovery operations in a microservices architecture. It declares methods that clients and services can use to interact through the service discovery system.
      public interface ServiceDiscovery {
         void registerClient(final Client client);
         void registerService(final Service service);
         void discoverService(final Client client, final String serviceName);
         void notifyAvailability(final Service service, final String serviceName);
      }
    • The Concrete Mediator:
      The Concrete Mediator implements the service discovery coordination logic between clients and services. It maintains a registry of all participants and facilitates service discovery operations.
      public class ServiceDiscoveryMediator implements ServiceDiscovery {
         private List<Client> clients = new ArrayList<>();
         private List<Service> services = new ArrayList<>();
      
         public void registerClient(final Client client) {
             clients.add(client);
             System.out.println("ServiceDiscovery: Registered client " + client.getId());
         }
      
         public void registerService(final Service service) {
             services.add(service);
             System.out.println("ServiceDiscovery: Registered service " + service.getId());
         }
      
         public void discoverService(final Client client, final String serviceName) {
             System.out.println("ServiceDiscovery: Processing discovery request for " + serviceName);
             for (Service service : services) {
                 service.receiveDiscoveryRequest(client, serviceName);
             }
         }
      
         public void notifyAvailability(final Service service, final String serviceName) {
             System.out.println("ServiceDiscovery: Processing availability notification for " + serviceName);
             for (Client client : clients) {
                 client.receiveServiceInfo(service, serviceName);
             }
         }
      }
    • The Colleague Interface:
      The Colleague interface defines the common contract for all participants in the mediated communication. Both clients and services implement this interface to ensure consistent interaction with the mediator.
      public interface Colleague {
         String getId();
         void setMediator(final ServiceDiscovery mediator);
      }
    • The Colleague Classes:
      Colleague classes represent clients and services in a microservices architecture. They communicate with each other only through the service discovery mediator, promoting loose coupling.

      Client Colleague:
      public class Client implements Colleague {
         private final String id;
         private ServiceDiscovery mediator;
      
         public Client(final String id) {
             this.id = id;
         }
      
         public String getId() {
             return id;
         }
      
         public void setMediator(final ServiceDiscovery mediator) {
             this.mediator = mediator;
         }
      
         public void discoverService(final String serviceName) {
             System.out.println("[Client " + id + "] Discovering service: " + serviceName);
             mediator.discoverService(this, serviceName);
         }
      
         public void receiveServiceInfo(final Service service, final String serviceName) {
             System.out.println("[Client " + id + "] Received info: Service '" + 
                               service.getId() + "' provides: " + serviceName);
         }
      }
      Service Colleague:
      public class Service implements Colleague {
         private final String id;
         private ServiceDiscovery mediator;
      
         public Service(final String id) {
             this.id = id;
         }
      
         public String getId() {
             return id;
         }
      
         public void setMediator(final ServiceDiscovery mediator) {
             this.mediator = mediator;
         }
      
         public void notifyAvailability(final String serviceName) {
             System.out.println("[Service " + id + "] Notifying availability of: " + serviceName);
             mediator.notifyAvailability(this, serviceName);
         }
      
         public void receiveDiscoveryRequest(final Client client, final String serviceName) {
             System.out.println("[Service " + id + "] Received discovery request from Client '" + 
                               client.getId() + "' for: " + serviceName);
         }
      }
    • Testing the Mediator Pattern:
      The client code demonstrates how clients and services communicate through the service discovery mediator. This simulates a microservices environment where the mediator facilitates all service discovery operations.
      public class MediatorPatternTest {
         public static void main(String[] args) {
             // Create the service discovery mediator
             ServiceDiscovery serviceDiscovery = new ServiceDiscoveryMediator();
      
             // Create clients and services
             Client client1 = new Client("client1");
             Client client2 = new Client("client2");
             Service service1 = new Service("ocr-service");
             Service service2 = new Service("tika-service");
      
             // Set mediator for all colleagues
             client1.setMediator(serviceDiscovery);
             client2.setMediator(serviceDiscovery);
             service1.setMediator(serviceDiscovery);
             service2.setMediator(serviceDiscovery);
      
             // Register colleagues with service discovery
             serviceDiscovery.registerClient(client1);
             serviceDiscovery.registerClient(client2);
             serviceDiscovery.registerService(service1);
             serviceDiscovery.registerService(service2);
      
             System.out.println("Service Discovery");
             client1.discoverService("ocr-api");
      
             System.out.println("Service Availability Notification");
             service1.notifyAvailability("ocr-processing");
         }
      }
© 2025 mtitek