143.25K
Категория: ПрограммированиеПрограммирование

09_Поведенческие_паттерны_проектирования

1.

Поведенческие паттерны
проектирования

2.

Задачи паттернов проектирования
Паттерны поведения связаны с алгоритмами и распределением
обязанностей между объектами.
Речь в них идет не только о самих объектах и классах, но и о типичных
способах взаимодействия.
В паттернах поведения уровня класса используется наследование – чтобы
распределить поведение между разными классами.
В паттернах поведения уровня объектов используется не наследование, а
композиция.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
2

3.

Список поведенческих паттернов
Цепочка обязанностей
Команда
Интерпретатор
Итератор
Посредник
Хранитель
Наблюдатель
Состояние
Стратегия
Шаблонный метод
Посетитель
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
3

4.

Цепочка обязанностей
(Chain of Responsibility)
Назначение
◦ Позволяет избежать привязки отправителя запроса к его получателю, давая шанс
обработать запрос нескольким объектам.
◦ Связывает объекты-получатели в цепочку и передает запрос вдоль этой цепочки,
пока его не обработают.
Мотивация
◦ Нужна контекстно-зависимая оперативная справка в GUI пользователя, который
получает помощь по любой части интерфейса, щелкнув мышью.
◦ Содержание справки зависит от того, какой интерфейса и какой контекст.
◦ Логично организовать справку от конкретных разделов к общим.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
4

5.

Применимость
Используйте паттерн цепочка обязанностей, когда:
◦ есть более одного объекта, способного обработать запрос, причем настоящий
обработчик заранее неизвестен и должен быть найден автоматически;
◦ вы хотите отправить запрос одному из нескольких объектов, не указывая явно,
какому именно;
◦ набор объектов, способных обработать запрос, должен задаваться динамически.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
5

6.

Структура паттерна
преемник
Handler
Client
HandleRequest()
ConcreteHandle
ConcreteHandle
HandleRequest()
HandleRequest()
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
6

7.

Результаты использования паттерна
Освобождает объект от необходимости «знать», кто конкретно обработает
его запрос.
Предоставляет дополнительную гибкость при распределении
обязанностей между объектами.
Однако получение не гарантировано.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
7

8.

Команда (Command)
Назначение
◦ Инкапсулирует запрос как объект, позволяя тем самым задавать параметры
клиентов для обработки соответствующих запросов, ставить запросы в очередь или
протоколировать их, а также поддерживать отмену операций.
Мотивация
◦ Иногда необходимо посылать объектам запросы, ничего не зная о том, выполнение
какой операции запрошено и кто является получателем.
◦ Паттерн команда позволяет библиотечным объектам отправлять запросы
неизвестным объектам приложения, преобразовав сам запрос в объект.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
8

9.

Применимость
Используйте паттерн команда, когда:
◦ параметризовать объекты выполняемым действием, как в случае с пунктами меню;
◦ определять, ставить в очередь и выполнять запросы в разное время;
◦ поддержать отмену операций;
◦ поддержать протоколирование изменений, чтобы их можно было выполнить
повторно после аварийной остановки системы;
◦ структурировать систему на основе высокоуровневых операций, построенных из
примитивных.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
9

10.

Структура паттерна
Client
Invoker
Command
Execute()
Receiver
Action()
receiver
ConcreteComponent
Execute()
Соcтояние
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
10

11.

Результаты использования паттерна
Команда разрывает связь между объектом, инициирующим операцию, и
объектом, имеющим информацию о том, как ее выполнить.
Команды – это самые настоящие объекты.
Из простых команд можно собирать составные.
Добавлять новые команды легко, поскольку никакие существующие
классы изменять не нужно.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
11

12.

Интерпретатор (Interpreter)
Назначение
◦ Для заданного языка определяет представление его грамматики, а также
интерпретатор предложений этого языка.
Мотивация
◦ Если некоторая задача возникает часто, то имеет смысл представить ее конкретные
проявления в виде предложений на простом языке.
◦ Затем можно будет создать интерпретатор, который решает задачу, анализируя
предложения этого языка.
◦ Паттерн интерпретатор определяет грамматику простого языка, представляет
предложения на этом языке и интерпретирует их.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
12

13.

Применимость
Используйте паттерн интерпретатор, когда:
◦ есть язык для интерпретации, предложения которого можно представить в виде
абстрактных синтаксических деревьев;
◦ грамматика языка проста;
◦ эффективность не является главным критерием.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
13

14.

Структура паттерна
Client
AbstractExpression
Interpret(Context)
Context
TerminalExpression
NonterminalExpression
Interpret(Context)
Interpret(Context)
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
14

15.

Результаты использования паттерна
Грамматику легко изменять и расширять.
Простая реализация грамматики.
Сложные грамматики трудно сопровождать.
Добавление новых способов интерпретации выражений.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
15

16.

Итератор (Iterator)
Назначение
◦ Предоставляет способ последовательного доступа ко всем элементам составного
объекта, не раскрывая его внутреннего представления.
Мотивация
◦ Составной объект, скажем список, должен предоставлять способ доступа к своим
элементам, не раскрывая их внутреннюю структуру.
◦ Иногда требуется обходить список по-разному, в зависимости от решаемой задачи.
◦ Основная идея в том, чтобы за доступ к элементам и способ обхода отвечал не сам
список, а отдельный объект-итератор.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
16

17.

Применимость
Используйте паттерн итератор, когда:
◦ для доступа к содержимому агрегированных объектов без раскрытия их внутреннего
представления;
◦ для поддержки нескольких активных обходов одного и того же агрегированного
объекта;
◦ для предоставления единообразного интерфейса с целью обхода различных
агрегированных структур.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
17

18.

Структура паттерна
Aggregate
Client
Iterator
First()
Next()
IsDone()
CurrentItem()
CreateIterator()
ConcreteAggregate
ConcreteIterator
CreateIterator()
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
18

19.

Результаты использования паттерна
Поддерживает различные виды обхода агрегата.
Итераторы упрощают интерфейс класса Aggregate.
Одновременно для данного агрегата может быть активно несколько
обходов.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
19

20.

Посредник (Mediator)
Назначение
◦ Определяет объект, инкапсулирующий способ взаимодействия множества объектов.
◦ Посредник обеспечивает слабую связанность системы, избавляя объекты от
необходимости явно ссылаться друг на друга и позволяя тем самым независимо
изменять взаимодействия между ними.
Мотивация
◦ Объектно-ориентированное проектирование способствует распределению
некоторого поведения между объектами.
◦ В получившейся структуре объектов может возникнуть много связей или каждому
объекту придется иметь информацию обо всех остальных.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
20

21.

Применимость
Используйте паттерн посредник, когда:
◦ имеются объекты, связи между которыми сложны и четко определены,
а получающиеся при этом взаимозависимости не структурированы
и трудны для понимания;
◦ нельзя повторно использовать объект, поскольку он обменивается информацией со
многими другими объектами;
◦ поведение, распределенное между несколькими классами, должно поддаваться
настройке без порождения множества подклассов.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
21

22.

Структура паттерна
посредник
Mediator
Collegue
ConcreteCollegue1
ConcreteMediator
ConcreteCollegue2
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
22

23.

Результаты использования паттерна
Снижает число порождаемых подклассов.
Устраняет связанность между коллегами.
Упрощает протоколы взаимодействия объектов.
Абстрагирует способ кооперирования объектов.
Централизует управление.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
23

24.

Хранитель (Memento)
Назначение
◦ Не нарушая инкапсуляции, фиксирует и выносит за пределы объекта его внутреннее
состояние так, чтобы позднее можно было восстановить в нем объект.
Мотивация
◦ Иногда необходимо тем или иным способом зафиксировать внутреннее состояние
объекта.
◦ Но обычно объекты инкапсулируют все свое состояние или хотя бы его часть, делая
его недоступным для других объектов, так что сохранить состояние извне
невозможно.
◦ Хранитель — это объект, в котором сохраняется внутреннее состояния другого
объекта – хозяина хранителя.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
24

25.

Применимость
Используйте паттерн хранитель, когда:
◦ необходимо сохранить мгновенный снимок состояния объекта (или его части), чтобы
впоследствии объект можно было восстановить в том же состоянии;
◦ прямое получение этого состояния раскрывает детали реализации и нарушает
инкапсуляцию объекта.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
25

26.

Структура паттерна
Originator
Memento
SetMemento(Memento m)
CreateMemento()
GetState()
SetState()
state
state
return new Memento(state)
хранитель
Caretaker
state = m -> GetState()
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
26

27.

Результаты использования паттерна
Сохранение границ инкапсуляции.
Упрощает структуры хозяина.
Значительные издержки при использовании хранителей.
Определение «узкий» и «широкий» интерфейсы.
Скрытая плата за содержание хранителя.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
27

28.

Наблюдатель (Observer)
Назначение
◦ Определяет зависимость типа «один ко многим» между объектами таким образом,
что при изменении состояния одного объекта все зависящие от него оповещаются
об этом и автоматически обновляются.
Мотивация
◦ В результате разбиения системы на множество совместно работающих классов
появляется необходимость поддерживать согласованное состояние
взаимосвязанных объектов.
◦ Это может привести к жёсткой связанности объектов.
◦ Паттерн наблюдатель описывает, как устанавливать такие отношения без
существенных ограничений.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
28

29.

Применимость
Используйте паттерн наблюдатель, когда:
◦ у абстракции есть два аспекта, один из которых зависит от другого: инкапсуляции
этих аспектов в разные объекты позволяют изменять и повторно использовать их
независимо;
◦ при модификации одного объекта требуется изменить другие и вы не знаете,
сколько именно объектов нужно изменить;
◦ один объект должен оповещать других, не делая предположений об уведомляемых
объектах.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
29

30.

Структура паттерна
Subject
Observer
Attach(Observer)
Detach(Observer)
Notify()
Update()
Для всех наблюдателей o {
o -> Update()
}
ConcreteObserver
subject
Update()
ConcreteSubject
GetState()
SetState()
return subjectState
observerState
subjectState
observerState = subject -> GetState()
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
30

31.

Результаты использования паттерна
Паттерн наблюдатель позволяет изменять субъекты и наблюдатели
независимо друг от друга.
Реализована абстрактная связанность субъекта и наблюдателя.
Реализована поддержка широковещательных коммуникаций.
Возможны неожиданные обновления.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
31

32.

Состояние (State)
Назначение
◦ Позволяет объекту варьировать свое поведение в зависимости от внутреннего
состояния. Извне создается впечатление, что изменился класс объекта.
Мотивация
◦ Рассмотрим класс "Соединение", с помощью которого представлено сетевое
соединение.
◦ Объект этого класса может находиться в одном из нескольких состояний:
"Установлено", "Прослушивание", "Закрыто".
◦ Паттерн состояние описывает, каким образом объект "Соединение" может вести
себя по-разному, находясь в различных состояниях.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
32

33.

Применимость
Используйте паттерн состояние, когда:
◦ поведение объекта зависит от его состояния и должно изменяться во время
выполнения;
◦ в коде операций встречаются состоящие из многих ветвей условные операторы, в
которых выбор ветви зависит от состояния (обычно в таком случае состояние
представлено перечисляемыми константами).
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
33

34.

Структура паттерна
Context
state
State
Request()
state -> Handle()
Handle()
ConcreteStateA
ConcreteStateB
Handle()
Handle()
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
34

35.

Результаты использования паттерна
Локализует зависящее от состояния поведение и делит его на части,
соответствующие состояниям.
Делает явными переходы между состояниями.
Объекты состояния можно разделять.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
35

36.

Стратегия (Strategy)
Назначение
◦ Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их
взаимозаменяемыми. Стратегия позволяет изменять алгоритмы независимо от
клиентов, которые ими пользуются.
Мотивация
◦ Существует много алгоритмов для разбиения текста на строки.
◦ Жестко «зашивать» все подобные алгоритмы в классы, которые в них нуждаются
нежелательно:
◦ клиент усложняется;
◦ не хочется поддерживать неиспользуемые алгоритмы;
◦ добавления новых и модификации существующих алгоритмов усложняется.
◦ Проблем нет, если есть классы, инкапсулирующие различные алгоритмы.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
36

37.

Применимость
Используйте паттерн стратегия, когда:
◦ имеется много родственных классов, отличающихся только поведением;
◦ вам нужно иметь несколько разных вариантов алгоритма;
◦ в алгоритме содержатся данные, о которых клиент не должен «знать»;
◦ в классе определено много поведений, что представлено разветвленными
условными операторами.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
37

38.

Структура паттерна
Context
strategy
Strategy
ContextInterface()
AlgorithmInterface()
ConcreteStrategyA
ConcreteStrategyB
AlgorithmInterface()
AlgorithmInterface()
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
38

39.

Результаты использования паттерна
Определяет семейство алгоритмов или поведений, которые можно
повторно использовать в разных контекстах.
Предоставляет альтернативу порождению подклассов.
Помогает избавиться от условных операторов.
Предлагает различные реализации одного и того же поведения.
Клиенты должны знать о различных стратегиях.
Возможен обмен лишней информацией между стратегией и контекстом.
Увеличивает число объектов.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
39

40.

Шаблонный метод (Template Method)
Назначение
◦ Шаблонный метод определяет основу алгоритма и позволяет подклассам
переопределить некоторые шаги алгоритма, не изменяя его структуру в целом.
Мотивация
◦ Пусть есть приложение работающее с документами.
◦ Документы могут быть разных типов.
◦ Реализуется операция OpenDocument() вне зависимости от типа документа.
◦ Такую операцию будем называть шаблонным методом.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
40

41.

Применимость
Используйте паттерн шаблонный метод, когда:
◦ нужно однократно использовать инвариантные части алгоритма, оставляя
реализацию изменяющегося поведения на усмотрение подклассов;
◦ нужно вычленить и локализовать в одном классе поведение, общее для всех
подклассов, дабы избежать дублирования кода;
◦ требуется управления расширениями подклассов.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
41

42.

Структура паттерна
AbstractClass
TemplateMethod()
PrimitiveOperation1()
PrimitiveOperation2()

PrimitiveOperation1()

PrimitiveOperation2()

ConcreteClass
PrimitiveOperation1()
PrimitiveOperation2()
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
42

43.

Результаты использования паттерна
Предоставляют возможность вынести общее поведение в библиотечные
классы.
Приводят к инвертированной структуре кода (родительский класс
вызывает операции подкласса).
Вызывают операции следующих видов:
◦ конкретные операции из класса ConcreteClass или ClientClass;
◦ конкретные операции из класса AbstractClass;
◦ примитивные операции;
◦ фабричные методы;
◦ операции-зацепки, реализующие поведение по умолчанию.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
43

44.

Посетитель (Visitor)
Назначение
◦ Описывает операцию, выполняемую с каждым объектом из некоторой структуры.
Паттерн посетитель позволяет определить новую операцию, не изменяя классы этих
объектов.
Мотивация
◦ Есть набор объектов различных классов.
◦ Нужно сохранить информацию, хранимую в них, но такой функционал изначально в
них не заложен и менять классы нельзя.
◦ Посетитель реализует просмотр объектов и сбор данных из них, причём объекты о
нём ничего не обязаны знать.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
44

45.

Применимость
Используйте паттерн , когда:
◦ в структуре присутствуют объекты многих классов с различными интерфейсами и вы
хотите выполнять над ними операции, зависящие от конкретных классов;
◦ над объектами, входящими в состав структуры, надо выполнять разнообразные, не
связанные между собой операции и вы не хотите «засорять» классы такими
операциями;
◦ классы, устанавливающие структуру объектов, изменяются редко, но новые
операции над этой структурой добавляются часто.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
45

46.

Структура паттерна
Visitor
VisitConcreteElementA(ConcreteElementA)
VisitConcreteElementB(ConcreteElementB)
Client
ConcreteVisitor1
VisitConcreteElementA(ConcreteElementA)
VisitConcreteElementB(ConcreteElementB)
ObjectStructure
ConcreteElementA
Accept(Visitor v)
OperationA()
ConcreteVisitor1
VisitConcreteElementA(ConcreteElementA)
VisitConcreteElementB(ConcreteElementB)
Element
Accept(Visitor)
v -> VisitConcreteElementA(this)
ConcreteElementB
Accept(Visitor v)
OperationB()
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
v -> VisitConcreteElementB(this)
46

47.

Результаты использования паттерна
Упрощает добавление новых операций.
Объединяет родственные операции и отсекает те, которые не имеют к
ним отношения.
Добавление новых классов ConcreteElement затруднено.
Посещает различные иерархии классов.
Аккумулирует состояния объектов.
Вызывает нарушение инкапсуляции объектов.
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
47

48.

Вопросы по лекции
1. Какой метод позволяет управлять многими объектами без их
модификации?
2. Какой паттерн используется для реализации отмены действия?
3. Какой паттерн инкапсулирует различные алгоритмы поведения?
ПОВЕДЕНЧЕСКИЕ ПАТТЕРНЫ
48
English     Русский Правила