Статьи

Шаблон дизайна посредника в Java

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

В паттерне медиатора мы извлекаем все отношения между различными классами в отдельном классе, известном как медиатор. Это позволяет нам вносить изменения в один компонент, не влияя на всю систему.

Итак, у нас есть более слабосвязанная система, которую проще расширять и обслуживать.

Представление UML:

Мы можем представить шаблон посредника с помощью следующей диаграммы UML:

Здесь мы имеем:

  • Посредник: интерфейс или абстрактный класс, определяющий договор для общения между коллегами
  • ConcreteMediator: класс, реализующий посреднический контракт; он знает обо всех коллегах и их взаимосвязях. Любое общение между коллегами происходит только через посредника
  • Коллега: интерфейс или абстрактный класс, представляющий компоненты нашей системы
  • ConcreteColleague: классы, которые реализуют интерфейс Colleague и готовы взаимодействовать друг с другом

Реализация шаблона посредника:

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

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

Давайте начнем с определения AircraftMediator и AircraftTrafficControlRoom :

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
30
31
32
33
34
35
36
public interface AircraftMediator {
  
    public void registerRunway(Runway runway);
    public String allotRunwayTo(Aircraft aircraft);    
    public void releaseRunwayOccupiedBy(Aircraft aircraft);
}
  
public class AicraftTrafficControlRoom implements AircraftMediator {
     
    private LinkedList<Runway> availableRunways = new LinkedList<>();
    private Map<Aircraft, Runway> aircraftRunwayMap = new HashMap<>();
  
    @Override
    public void registerRunway(Runway runway) {
        this.availableRunways.add(runway);
    }
  
    @Override
    public String allotRunwayTo(Aircraft aircraft) {
        Runway nextAvailbleRunway = null;
        if(!this.availableRunways.isEmpty()) {
            nextAvailbleRunway = this.availableRunways.removeFirst();
            this.aircraftRunwayMap.put(aircraft, runway);
        }
        return nextAvailbleRunway == null ?
          null : nextAvailbleRunway.getName();
    }
  
    @Override
    public void releaseRunwayOccupiedBy(Aircraft aircraft) {
        if(this.aircraftRunwayMap.containsKey(aircraft)) {
            Runway runway = this.aircraftRunwayMap.remove(aircraft);
            this.availableRunways.add(runway);
        }
    }
}

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

Определение коллег:

Теперь давайте определимся с нашими самолетами , экземплярами которых станут коллеги:

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
30
31
32
public interface AircraftColleague {
    void startLanding();
    void finishLanding();
}
  
public class Aircraft implements AircraftColleague {
  
    private AircraftMediator mediator;
    private String flightName;
  
    public Aircraft(AircraftMediator mediator, String flightName) {
        this.mediator = mediator;
        this.flightName = flightName;
    }
  
    @Override
    public void startLanding() {
        String runway = this.mediator.allotRunwayTo(this);
        if(runway == null) {
            //informing passengers
            System.out.println("Due to traffic, there's a delay in landing of " + this.flightName );  
        } else {
            System.out.println("Currently landing " + this.flightName + " on " + runway);  
        }  
    }
  
    @Override
    public void finishLanding() {
       System.out.println(this.flightName + "landed successfully");
       this.mediator.releaseRunwayOccupiedBy(this);
    }
}

Тестирование нашей реализации:

Давайте посмотрим, как это работает вместе:

01
02
03
04
05
06
07
08
09
10
11
12
// In our main method
Runway runwayA = new Runway("Runway A");
  
AircraftMediator mediator = new AircraftTrafficControlRoom();
mediator.registerRunway(runwayA);
  
AircraftColleague wrightFlight = new Aircraft(mediator, "Wright Flight");
AircraftColleague airbusA380 = new Aircraft(mediator, "Airbus A380");
  
wrightFlight.startLanding();
airbusA380.startLanding();
wrightFlight.finishLanding();

При выполнении приведенного выше кода у нас будет следующий вывод:

1
2
3
Currently landing Wright Flight on Runway A
Due to traffic, there's a delay in landing of Airbus A380
Wright Flight landed successfully

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

Вывод:

В этом уроке мы узнали, как реализовать шаблон посредника. Мы будем использовать шаблон-посредник, когда у нас есть система, в которой несколько объектов взаимодействуют друг с другом. Эта схема способствует слабому сцеплению и тем самым делает систему более гибкой.

Распространенным применением этого шаблона является система чата или обмена сообщениями. Кроме того, метод execute () Java Concurrency Executor использует этот шаблон.

Опубликовано на Java Code Geeks с разрешения Шубхры Шриваставы, партнера нашей программы JCG . Посмотрите оригинальную статью здесь: Шаблон дизайна посредника в Java

Мнения, высказанные участниками Java Code Geeks, являются их собственными.