Jump to content

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

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

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

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

Посредник [1] Шаблон проектирования — один из двадцати трех хорошо известных шаблонов проектирования , которые описывают, как решать повторяющиеся проблемы проектирования для разработки гибкого и многократно используемого объектно-ориентированного программного обеспечения, то есть объектов, которые легче реализовать, изменить, протестировать и повторно использовать.

Проблемы, которые может решить шаблон проектирования посредника [2]

[ редактировать ]
  • Следует избегать тесной связи между набором взаимодействующих объектов.
  • Должна быть возможность самостоятельно изменять взаимодействие между набором объектов.

Определение набора взаимодействующих объектов путем прямого доступа и обновления друг друга негибко, поскольку оно тесно связывает объекты друг с другом и делает невозможным изменение взаимодействия независимо от объектов (без необходимости изменения). И это препятствует повторному использованию объектов и затрудняет их тестирование.

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

Решения, описываемые шаблоном проектирования посредника

[ редактировать ]
  • Определите отдельный объект (посредник), который инкапсулирует взаимодействие между набором объектов.
  • Объекты делегируют свое взаимодействие объекту-посреднику вместо того, чтобы взаимодействовать друг с другом напрямую.

Объекты взаимодействуют друг с другом косвенно через объект-посредник, который контролирует и координирует взаимодействие.

Это делает объекты слабо связанными . Они ссылаются только на свой объект-посредник и знают о нем и не имеют явных знаний друг о друге.

См. также класс UML и диаграмму последовательности ниже.

Определение

[ редактировать ]

Суть шаблона посредника заключается в «определении объекта, который инкапсулирует взаимодействие набора объектов». Он способствует слабой связи, не позволяя объектам явно ссылаться друг на друга, и позволяет независимо изменять их взаимодействие. [3] [4] Клиентские классы могут использовать посредник для отправки сообщений другим клиентам и могут получать сообщения от других клиентов через событие в классе посредника.

Структура

[ редактировать ]

Класс UML и диаграмма последовательности

[ редактировать ]
Пример класса UML и диаграммы последовательности для шаблона проектирования посредника. [5]

На приведенной выше UML классов диаграмме Colleague1 и Colleague2 классы не ссылаются (и не обновляют) друг на друга напрямую. Вместо этого они относятся к общему Mediator интерфейс для контроля и координации взаимодействия ( mediate()), что делает их независимыми друг от друга в отношении способа осуществления взаимодействия. Mediator1 класс реализует взаимодействие между Colleague1 и Colleague2.

Диаграмма UML последовательности показывает взаимодействие во время выполнения. В этом примере Mediator1 объект опосредует (контролирует и координирует) взаимодействие между Colleague1 и Colleague2 объекты.

Предполагая, что Colleague1 хочет взаимодействовать с Colleague2 (например, для обновления/синхронизации его состояния), Colleague1 звонки mediate(this) на Mediator1 объект, который получает измененные данные из Colleague1 и выполняет action2() на Colleague2.

После этого Colleague2 звонки mediate(this) на Mediator1 объект, который получает измененные данные из Colleague2 и выполняет action1() на Colleague1.

Диаграмма классов

[ редактировать ]
Шаблон поведенческого проектирования посредника
Участники

Медиатор — определяет интерфейс для связи между Коллеги объектами .

ConcreteMediator — реализует интерфейс посредника и координирует связь между объектами «Коллега» . Он осведомлен обо всех коллегах и их целях в отношении взаимодействия.

Коллега – определяет интерфейс для общения с другими Коллегами через своего Посредника.

ConcreteColleague — реализует интерфейс Коллеги и общается с другими Коллегами через своего Медиатора.

Шаблон посредника гарантирует, что компоненты слабо связаны , так что они не вызывают друг друга явно, а вместо этого делают это посредством вызовов посредника. В следующем примере посредник регистрирует все компоненты, а затем вызывает их методы SetState.

interface IComponent
{
    void SetState(object state);
}

class Component1 : IComponent
{
    internal void SetState(object state)
    {
        throw new NotImplementedException();
    }
}

class Component2 : IComponent
{
    internal void SetState(object state)
    {
        throw new NotImplementedException();
    }
}

// Mediates the common tasks
class Mediator
{
    internal IComponent Component1 { get; set; }
    internal IComponent Component2 { get; set; }

    internal void ChangeState(object state)
    {
        this.Component1.SetState(state);
        this.Component2.SetState(state);
    }
}

Чат может использовать шаблон посредника или систему, в которой каждый из множества «клиентов» получает сообщение каждый раз, когда один из других клиентов выполняет действие (для чатов это будет когда каждый человек отправляет сообщение). В действительности использование шаблона посредника для чата будет практичным только при использовании удаленного взаимодействия . Использование необработанных сокетов не позволило бы использовать делегата обратные вызовы (люди подписались на событие MessageReceived класса Mediator).

public delegate void MessageReceivedEventHandler(string message, string sender);

public class Mediator
{
    public event MessageReceivedEventHandler MessageReceived;

    public void Send(string message, string sender)
    {
        if (MessageReceived != null)
        {
            Console.WriteLine("Sending '{0}' from {1}", message, sender);
            MessageReceived(message, sender);
        }
    }
}

public class Person
{
    private Mediator _mediator;

    public string Name { get; set; }

    public Person(Mediator mediator, string name)
    {
        Name = name;
        _mediator = mediator;
        _mediator.MessageReceived += new MessageReceivedEventHandler(Receive);
    }

    private void Receive(string message, string sender)
    {
        if (sender != Name)
            Console.WriteLine("{0} received '{1}' from {2}", Name, message, sender);
    }

    public void Send(string message)
    {
        _mediator.Send(message, Name);
    }
}

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

import java.util.HashMap;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;

class Storage<T> {
    T value;
    
    T getValue() {
        return value;
    }
    void setValue(Mediator<T> mediator, String storageName, T value) {
        this.value = value;
        mediator.notifyObservers(storageName);
    }
}

class Mediator<T> {
    private final HashMap<String, Storage<T>> storageMap = new HashMap<>();
    private final CopyOnWriteArrayList<Consumer<String>> observers = new CopyOnWriteArrayList<>();
    
    public void setValue(String storageName, T value) {
        Storage storage = storageMap.computeIfAbsent(storageName, name -> new Storage<>());
        storage.setValue(this, storageName, value);
    }
    
    public Optional<T> getValue(String storageName) {
        return Optional.ofNullable(storageMap.get(storageName)).map(Storage::getValue);
    }
    
    public void addObserver(String storageName, Runnable observer) {
        observers.add(eventName -> {
            if (eventName.equals(storageName)) {
                observer.run();
            }
        });
    }
    
    void notifyObservers(String eventName) {
        observers.forEach(observer -> observer.accept(eventName));
    }
}

public class MediatorDemo {
    public static void main(String[] args) {
        Mediator<Integer> mediator = new Mediator<>();
        mediator.setValue("bob", 20);
        mediator.setValue("alice", 24);
        mediator.getValue("alice").ifPresent(age -> System.out.println("age for alice: " + age));
        
        mediator.addObserver("bob", () -> {
            System.out.println("new age for bob: " + mediator.getValue("bob").orElseThrow(RuntimeException::new));
        });
        mediator.setValue("bob", 21);
    }
}

См. также

[ редактировать ]
  1. ^ Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес (1994). Шаблоны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования . Эддисон Уэсли. стр. 273 и далее . ISBN  0-201-63361-2 . {{cite book}}: CS1 maint: несколько имен: список авторов ( ссылка )
  2. ^ Франке, Гюнтер. «Шаблон проектирования «Посредник» — проблема, решение и применимость» . w3sDesign . Проверено 12 августа 2017 г.
  3. ^ Гамма, Эрих ; Хелм, Ричард; Джонсон, Ральф ; Влиссидес, Джон (1994). Шаблоны проектирования . Аддисон-Уэсли . ISBN  0-201-63361-2 .
  4. ^ «Шаблон проектирования посредника» . Создание исходников .
  5. ^ Франке, Гюнтер. «Шаблон проектирования Посредник — структура и сотрудничество» . w3sDesign . Проверено 12 августа 2017 г.
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 881d9198e852c91340dd03b6f6ea3844__1720781700
URL1:https://arc.ask3.ru/arc/aa/88/44/881d9198e852c91340dd03b6f6ea3844.html
Заголовок, (Title) документа по адресу, URL1:
Mediator pattern - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)