Статьи

Шаблон проектирования посредника в Java — пример учебного пособия

Посреднический паттерн — это один из паттернов поведенческого проектирования , поэтому он имеет дело с поведением объектов. Шаблон проектирования посредника используется для обеспечения централизованной среды связи между различными объектами в системе. Согласно GoF, намерение посредника:

Позволяет слабой связи, инкапсулируя способ взаимодействия и связи разнородных наборов объектов. Позволяет действиям каждого объекта изменяться независимо друг от друга.

Шаблон проектирования посредника очень полезен в корпоративном приложении, где несколько объектов взаимодействуют друг с другом. Если объекты взаимодействуют друг с другом напрямую, компоненты системы тесно связаны друг с другом, что повышает стоимость обслуживания и не позволяет легко расширяться. Шаблон посредника фокусируется на предоставлении посредника между объектами для связи и помощи в реализации потери связи между объектами.

Авиадиспетчер является отличным примером посреднической схемы, когда диспетчерский пункт аэропорта выступает в качестве посредника для связи между различными рейсами. Посредник работает как маршрутизатор между объектами и может иметь собственную логику для обеспечения связи.

Системные объекты, которые общаются друг с другом, называются коллегами. Обычно у нас есть интерфейс или абстрактный класс, который предоставляет контракт для связи, а затем у нас есть конкретная реализация посредников.

В нашем примере мы попытаемся реализовать приложение для чата, где пользователи могут вести групповой чат. Каждый пользователь будет идентифицирован по имени, и они могут отправлять и получать сообщения. Сообщение, отправленное любым пользователем, должно быть получено всеми другими пользователями в группе.

Интерфейс посредника

Прежде всего, мы создадим интерфейс посредника, который будет определять контракт для конкретных посредников.

1
2
3
4
5
6
7
8
package com.journaldev.design.mediator;
 
public interface ChatMediator {
 
    public void sendMessage(String msg, User user);
 
    void addUser(User user);
}

Интерфейс коллеги

Пользователи могут отправлять и получать сообщения, поэтому мы можем иметь пользовательский интерфейс или абстрактный класс. Я создаю пользователя как абстрактный класс, как показано ниже.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
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);
}

Обратите внимание, что у пользователя есть ссылка на объект-посредник, он необходим для связи между разными пользователями.

Конкретный Медиатор

Теперь мы создадим конкретный класс-посредник, он будет иметь список пользователей в группе и предоставит логику для общения между пользователями.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.journaldev.design.mediator;
 
import java.util.ArrayList;
import java.util.List;
 
public class ChatMediatorImpl implements ChatMediator {
 
    private List<User> 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){
            //message should not be received by the user sending it
            if(u != user){
                u.receive(msg);
            }
        }
    }
 
}

Конкретный Коллега

Теперь мы можем создавать конкретные пользовательские классы для использования клиентской системой.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
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);
    }
 
}

Обратите внимание, что метод send () использует посредник для отправки сообщения пользователям, и он не знает, как он будет обрабатываться посредником.

Mediator Pattern Client

Давайте протестируем это наше приложение для чата с помощью простой программы, в которой мы создадим посредника и добавим пользователей в группу, а один из пользователей отправит сообщение.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
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");
 
    }
 
}

Обратите внимание, что клиентская программа очень проста, и она не знает, как обрабатывается сообщение и получает ли посредник пользователя или нет.

Вывод вышеуказанной программы:

1
2
3
4
Pankaj: Sending Message=Hi All
Lisa: Received Message:Hi All
Saurabh: Received Message:Hi All
David: Received Message:Hi All

Диаграмма классов паттернов-посредников

Посредник-паттерн

Образец посредника в JDK

Важные точки

  • Шаблон посредника полезен, когда логика коммуникации между объектами сложна, у нас может быть центральная точка коммуникации, которая заботится о логике коммуникации.
  • Служба сообщений Java (JMS) использует шаблон Mediator вместе с шаблоном Observer, чтобы позволить приложениям подписываться и публиковать данные в других приложениях.
  • Мы не должны использовать модель посредников только для того, чтобы добиться потерянной связи, потому что, если число посредников будет расти, их будет сложно поддерживать.