Шаблон посредника - Mediator pattern
В программная инженерия, то образец посредника определяет объект, который инкапсулирует как взаимодействуют объекты. Этот узор считается поведенческий образец из-за того, что он может изменить поведение программы.
В объектно-ориентированном программировании программы часто состоят из множества классы. Бизнес-логика и вычисление распределяются между этими классами. Однако по мере того, как в программу добавляется больше классов, особенно во время поддержание и / или рефакторинг, проблема коммуникация между этими классами может стать более сложным. Это затрудняет чтение и сопровождение программы. Кроме того, изменить программу может быть сложно, поскольку любое изменение может повлиять на код в некоторых других классах.
С образец посредникасвязь между объектами заключена в посредник объект. Объекты больше не общаются друг с другом напрямую, а общаются через посредника. Это уменьшает зависимости между взаимодействующими объектами, тем самым уменьшая связь.
Обзор
Посредник[1] шаблон дизайна - один из двадцати трех хорошо известных шаблоны проектирования в которых описывается, как решать повторяющиеся проблемы проектирования для разработки гибкого и многократно используемого объектно-ориентированного программного обеспечения, то есть объектов, которые легче реализовать, изменить, протестировать и повторно использовать.
Какие проблемы может решить шаблон проектирования Посредник?[2]
- Следует избегать тесной связи между набором взаимодействующих объектов.
- Должна существовать возможность изменять взаимодействие между набором объектов независимо.
Определение набора взаимодействующих объектов путем прямого доступа и обновления друг друга является негибким, потому что оно тесно связывает объекты друг с другом и делает невозможным изменение взаимодействия независимо от объектов (без необходимости изменения), а также предотвращает создание объектов. многоразовые и затрудняют их тестирование.
Сильно связанные объекты их сложно реализовать, изменить, протестировать и повторно использовать, потому что они относятся к множеству различных объектов и знают о них.
Какое решение описывает шаблон проектирования Посредник?
- Определите отдельный объект (посредник), который инкапсулирует взаимодействие между набором объектов.
- Объекты делегируют свое взаимодействие объекту-посреднику вместо того, чтобы взаимодействовать друг с другом напрямую.
Объекты взаимодействуют друг с другом косвенно через объект-посредник, который контролирует и координирует взаимодействие.
Это делает объекты слабо связанный. Они только ссылаются на свой объект-посредник и знают о нем и не имеют явного знания друг о друге.
См. Также схему классов и последовательности UML ниже.
Определение
Суть паттерна посредника состоит в том, чтобы «определить объект, который инкапсулирует, как взаимодействует набор объектов». Он способствует слабой связи, не позволяя объектам явно ссылаться друг на друга, и позволяет изменять их взаимодействие независимо друг от друга.[3][4] Классы клиентов могут использовать посредника для отправки сообщений другим клиентам и могут получать сообщения от других клиентов через событие в классе посредника.
Структура
Схема классов и последовательности UML
В приведенном выше UML диаграмма классов, то Коллега1
и Коллега2
классы не ссылаются (и не обновляют) друг друга напрямую, а вместо этого относятся к общим Посредник
интерфейс для управления и координации взаимодействия (посредничать ()
), что делает их независимыми друг от друга в том, как осуществляется взаимодействие. Посредник1
класс реализует взаимодействие между Коллега1
и Коллега2
.
В UML схема последовательности показывает взаимодействия во время выполнения. В этом примере Посредник1
объект опосредует (контролирует и координирует) взаимодействие между Коллега1
и Коллега2
объекты.
При условии, что Коллега1
хочет взаимодействовать с Коллега2
(например, для обновления / синхронизации своего состояния), Коллега1
звонки посредничать (это)
на Посредник1
объект, который получает измененные данные из Коллега1
и выполняет действие2 ()
на Коллега2
.
После этогоКоллега2
звонки посредничать (это)
на Посредник1
объект, который получает измененные данные из Коллега2
и выполняет действие1 ()
на Коллега1
.
Диаграмма классов
- Участников
Посредник - определяет интерфейс для связи между Коллега объекты
БетонМедиатор - реализует интерфейс посредника и координирует связь между Коллега объекты. Он знает обо всех Коллеги по работе и их цели в отношении взаимодействия.
Коллега - определяет интерфейс для связи с другими Коллеги по работе через его Посредник
БетонКоллига - реализует интерфейс Коллеги и общается с другими Коллеги по работе через его Посредник
пример
C #
Шаблон посредника гарантирует, что компоненты слабо связанный, так что они не вызывают друг друга явно, а вместо этого делают это через вызовы посредника. В следующем примере посредник регистрирует все компоненты, а затем вызывает их методы SetState.
интерфейс IComponent{ пустота SetState(объект штат);}класс Компонент1 : IComponent{ внутренний пустота SetState(объект штат) { бросить новый NotImplementedException(); }}класс Компонент2 : IComponent{ внутренний пустота SetState(объект штат) { бросить новый NotImplementedException(); }}// Выполняет общие задачикласс Посредник{ внутренний IComponent Компонент1 { получать; набор; } внутренний IComponent Компонент2 { получать; набор; } внутренний пустота ChangeState(объект штат) { этот.Компонент1.SetState(штат); этот.Компонент2.SetState(штат); }}
В чате можно использовать шаблон «Посредник» или систему, в которой каждый из многих «клиентов» получает сообщение каждый раз, когда один из других клиентов выполняет какое-либо действие (для чатов это будет когда каждый человек отправляет сообщение). На самом деле использование шаблона Посредника для чата будет практичным только при использовании с удаленное взаимодействие. Использование сырых сокетов не позволит делегировать обратные вызовы (люди подписались на событие MessageReceived класса Mediator).
общественный делегировать пустота MessageReceivedEventHandler(строка сообщение, строка отправитель);общественный класс Посредник{ общественный мероприятие MessageReceivedEventHandler Сообщение доставлено; общественный пустота послать(строка сообщение, строка отправитель) { если (Сообщение доставлено != значение NULL) { Консоль.WriteLine("Отправка '{0}' от {1}", сообщение, отправитель); Сообщение доставлено(сообщение, отправитель); } }}общественный класс Человек{ частный Посредник _mediator; общественный строка имя { получать; набор; } общественный Человек(Посредник посредник, строка имя) { имя = имя; _mediator = посредник; _mediator.Сообщение доставлено += новый MessageReceivedEventHandler(Получить); } частный пустота Получить(строка сообщение, строка отправитель) { если (отправитель != имя) Консоль.WriteLine("{0} получил '{1}' от {2}", имя, сообщение, отправитель); } общественный пустота послать(строка сообщение) { _mediator.послать(сообщение, имя); }}
Ява
В следующем примере Посредник
объект управляет значениями нескольких Место хранения
объекты, заставляя код пользователя обращаться к сохраненным значениям через посредника. Когда объект хранения хочет создать событие, указывающее, что его значение изменилось, он также возвращается к объекту-посреднику (через метод notifyObservers
), который управляет списком наблюдателей (реализован с помощью образец наблюдателя ).
импорт java.util.HashMap;импорт java.util.Optional;импорт java.util.concurrent.CopyOnWriteArrayList;импорт java.util.function.Consumer;класс Место хранения<Т> { Т ценность; Т getValue() { вернуть ценность; } пустота setValue(Посредник<Т> посредник, Строка storageName, Т ценность) { этот.ценность = ценность; посредник.notifyObservers(storageName); }}класс Посредник<Т> { частный окончательный HashMap<Строка, Место хранения<Т>> StorageMap = новый HashMap<>(); частный окончательный CopyOnWriteArrayList<Потребитель<Строка>> наблюдатели = новый CopyOnWriteArrayList<>(); общественный пустота setValue(Строка storageName, Т ценность) { Место хранения место хранения = StorageMap.computeIfAbsent(storageName, имя -> новый Место хранения<>()); место хранения.setValue(этот, storageName, ценность); } общественный Необязательный<Т> getValue(Строка storageName) { вернуть Необязательный.ofNullable(StorageMap.получать(storageName)).карта(Место хранения::getValue); } общественный пустота addObserver(Строка storageName, Работоспособен наблюдатель) { наблюдатели.Добавить(название события -> { если (название события.равно(storageName)) { наблюдатель.бегать(); } }); } пустота notifyObservers(Строка название события) { наблюдатели.для каждого(наблюдатель -> наблюдатель.принять(название события)); }}общественный класс ПосредникДемо { общественный статический пустота основной(Строка[] аргументы) { Посредник<Целое число> посредник = новый Посредник<>(); посредник.setValue("боб", 20); посредник.setValue("алиса", 24); посредник.getValue("алиса").если имеется(возраст -> Система.вне.println("возраст для Алисы:" + возраст)); посредник.addObserver("боб", () -> { Система.вне.println("новый век для боба:" + посредник.getValue("боб").orElseThrow(RuntimeException::новый)); }); посредник.setValue("боб", 21); }}
Смотрите также
- Посредничество данных
- Шаблоны проектирования, книга, положившая начало изучению шаблонов проектирования в информатике
- Шаблон проектирования (информатика), стандартное решение распространенных проблем в разработке программного обеспечения
использованная литература
- ^ Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес (1994). Паттерны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования. Эддисон Уэсли. стр.273ff. ISBN 0-201-63361-2.CS1 maint: несколько имен: список авторов (ссылка на сайт)
- ^ Франке, Гюнтер. «Шаблон проектирования посредника - проблема, решение и применимость». w3sDesign. Получено 2017-08-12.
- ^ Гамма, Эрих; Хелм, Ричард; Джонсон, Ральф; Влиссидес, Джон (1994). Шаблоны проектирования. Эддисон-Уэсли. ISBN 0-201-63361-2.
- ^ "Шаблон дизайна посредника". Источник.
- ^ Франке, Гюнтер. «Шаблон проектирования посредника - структура и взаимодействие». w3sDesign. Получено 2017-08-12.
внешние ссылки
- Кайзер, Бодо (21 сентября 2012 г.). "Рекомендуется ли использование шаблона посредника?". Переполнение стека.