Рубрики
Без рубрики

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

Взгляните на концепцию шаблона проектирования посредника и реализацию Java

Автор оригинала: Krzysztof Woyke.

1. Обзор

В этой статье мы посмотрим на Шаблон посредника, один из Поведенческие модели GoF . Мы опишем его назначение и объясним, когда мы должны его использовать.

Как обычно, мы также предоставим простой пример кода.

2. Шаблон посредника

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

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

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

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

3. Диаграмма UML шаблона посредника

Давайте теперь посмотрим на шаблон визуально:

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

  • Посредник определяет интерфейс Коллега объекты, которые используются для общения
  • Коллега определяет абстрактный класс, держащий одну ссылку на посредник
  • БетонныйМедиатор инкапсулирует логику взаимодействия между Коллега Объектов
  • БетонКоллига1 и БетонКоллига2 общаться только через посредник

Как мы видим, Коллега объекты не относятся друг к другу напрямую. Вместо этого, все коммуникации осуществляется Посредник .

Следовательно, БетонКоллига1 и БетонКоллига2 может быть более легко повторно использованы.

Кроме того, в случае, если нам нужно изменить Коллега объекты работают вместе, мы только должны изменить БетонныйМедиатор логика. Или мы можем создать новую реализацию посредник.

4. Реализация Java

Теперь, когда у нас есть четкое представление о теории, давайте рассмотрим пример, чтобы лучше понять концепцию на практике.

4.1. Пример сценария

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

Давайте теперь рассмотрим пример реализации:

public class Button {
    private Fan fan;

    // constructor, getters and setters

    public void press(){
        if(fan.isOn()){
            fan.turnOff();
        } else {
            fan.turnOn();
        }
    }
}
public class Fan {
    private Button button;
    private PowerSupplier powerSupplier;
    private boolean isOn = false;

    // constructor, getters and setters

    public void turnOn() {
        powerSupplier.turnOn();
        isOn = true;
    }

    public void turnOff() {
        isOn = false;
        powerSupplier.turnOff();
    }
}
public class PowerSupplier {
    public void turnOn() {
        // implementation
    }

    public void turnOff() {
        // implementation
    }
}

Далее давайте проверьте функциональность:

@Test
public void givenTurnedOffFan_whenPressingButtonTwice_fanShouldTurnOnAndOff() {
    assertFalse(fan.isOn());

    button.press();
    assertTrue(fan.isOn());

    button.press();
    assertFalse(fan.isOn());
}

Кажется, все работает нормально. Но обратите внимание, Кнопка, Вентилятор, и PowerSupplier классы тесно связаны . Кнопка работает непосредственно на Вентилятор и Вентилятор взаимодействует с обоими Кнопка и PowerSupplier.

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

4.2. Добавление шаблона посредника

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

Во-первых, давайте представим Посредник класс:

public class Mediator {
    private Button button;
    private Fan fan;
    private PowerSupplier powerSupplier;

    // constructor, getters and setters

    public void press() {
        if (fan.isOn()) {
            fan.turnOff();
        } else {
            fan.turnOn();
        }
    }

    public void start() {
        powerSupplier.turnOn();
    }

    public void stop() {
        powerSupplier.turnOff();
    }
}

Далее давайте изменим остальные классы:

public class Button {
    private Mediator mediator;

    // constructor, getters and setters

    public void press() {
        mediator.press();
    }
}
public class Fan {
    private Mediator mediator;
    private boolean isOn = false;

    // constructor, getters and setters

    public void turnOn() {
        mediator.start();
        isOn = true;
    }

    public void turnOff() {
        isOn = false;
        mediator.stop();
    }
}

Опять же, давайте проверить функциональность:

@Test
public void givenTurnedOffFan_whenPressingButtonTwice_fanShouldTurnOnAndOff() {
    assertFalse(fan.isOn());
 
    button.press();
    assertTrue(fan.isOn());
 
    button.press();
    assertFalse(fan.isOn());
}

Наша система охлаждения работает в том же, что и ожидалось.

Теперь, когда мы внедрили шаблон посредника, ни один из Кнопка , Вентилятор , или PowerSupplier классы общаются напрямую . У них есть только одна ссылка на посредник.

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

Этот пример показывает, как легко мы можем отделить зависимые объекты и сделать нашу систему проще в обслуживании.

5. Когда использовать шаблон посредника

Шаблон Посредника является хорошим выбором, если нам придется иметь дело с набором объектов, которые тесно связаны и трудно поддерживать. Таким образом, мы можем уменьшить зависимости между объектами и уменьшить общую сложность.

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

Иногда, однако, мы можем иметь слишком много плотно соединенных объектов из-за неисправного дизайна системы. Если это так, мы не должны применять шаблон посредника . Вместо этого мы должны сделать один шаг назад и переосмыслить то, как мы моделированы наши классы.

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

6. Заключение

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

Как всегда, полные образцы кода доступны более на GitHub .