- •197110, Санкт-Петербург, Чкаловский пр., 15.
- •Глава 1. Введение в паттерны проектирования 15
- •Глава 2. Проектирование редактора документов 39
- •Глава 3. Порождающие паттерны 75
- •Глава 4. Структурные паттерны 109
- •Глава 5. Паттерны поведения 173
- •Глава 6. Заключение 271
- •Предисловие
- •Глава 1. Введение в паттерны проектирования
- •1.1. Что такое паттерн проектирования
- •1.2. Паттерны проектирования в схеме mvc в языке Smalltalk
- •1.3. Описание паттернов проектирования
- •1.4. Каталог паттернов проектирования
- •1.5. Организация каталога
- •1.6. Как решать задачи проектирования с помощью паттернов
- •Поиск подходящих объектов
- •Определение степени детализации объекта
- •Специфицирование интерфейсов объекта
- •Специфицирование реализации объектов
- •Механизмы повторного использования
- •Сравнение структур времени выполнения и времени компиляции
- •Проектирование с учетом будущих изменений
- •1.7. Как выбирать паттерн проектирования
- •1.8. Как пользоваться паттерном проектирования
- •Глава 2. Проектирование редактора документов
- •2.1. Задачи проектирования
- •2.2. Структура документа
- •Рекурсивная композиция
- •Паттерн компоновщик
- •2.3. Форматирование
- •Инкапсуляция алгоритма форматирования
- •Классы Compositor и Composition
- •Стратегия
- •2.4. Оформление пользовательского интерфейса
- •Прозрачное обрамление
- •Моноглиф
- •Паттерн декоратор
- •2.5. Поддержка нескольких стандартов внешнего облика
- •Абстрагирование создания объекта
- •Фабрики и изготовленные классы
- •Паттерн абстрактная фабрика
- •2.6. Поддержка нескольких оконных систем
- •Можно ли воспользоваться абстрактной фабрикой?
- •Инкапсуляция зависимостей от реализации
- •Классы Window и WindowImp
- •Подклассы WindowImp
- •Конфигурирование класса Window с помощью WindowImp
- •Паттерн мост
- •2.7. Операции пользователя
- •Инкапсуляция запроса
- •Класс Command и его подклассы
- •Отмена операций
- •История команд
- •Паттерн команда
- •2.8. Проверка правописания и расстановка переносов
- •Доступ к распределенной информации
- •Инкапсуляция доступа и порядка обхода
- •Класс Iterator и его подклассы
- •Паттерн итератор
- •Обход, и действия выполняемые при обходе
- •Класс Visitor и его подклассы
- •Паттерн посетитель
- •2.9. Резюме
- •Глава 3. Порождающие паттерны
- •Паттерн Abstract Factory
- •Паттерн Builder
- •Паттерн Factory Method
- •Паттерн Prototype
- •Паттерн Singleton
- •Обсуждение порождающих паттернов
- •Глава 4. Структурные паттерны
- •Паттерн Adapter
- •Паттерн Bridge
- •Паттерн Composite
- •Паттерн Decorator
- •Паттерн Facade
- •Паттерн Flyweight
- •Паттерн Proxy
- •Обсуждение структурных паттернов
- •Адаптер и мост
- •Компоновщик, декоратор и заместитель
- •Глава 5. Паттерны поведения
- •Паттерн Chain of Responsibility
- •Паттерн Command
- •Паттерн Interpreter
- •Паттерн Iterator
- •Паттерн Mediator
- •Паттерн Memento
- •Паттерн Observer
- •Паттерн State
- •Паттерн Strategy
- •Паттерн Template Method
- •Паттерн Visitor
- •Обсуждение паттернов поведения Инкапсуляция вариаций
- •Объекты как аргументы
- •Должен ли обмен информацией быть инкапсулированным или распределенным
- •Разделение получателей и отправителей
- •Глава 6. Заключение
- •6.1. Чего ожидать от паттернов проектирования
- •Единый словарь проектирования
- •Помощь при документировании и изучении
- •Дополнение существующих методов
- •Цель реорганизации
- •6.2. Краткая история
- •6.3. Проектировщики паттернов
- •Языки паттернов Александра
- •Паттерны в программном обеспечении
- •6.4. Приглашение
- •6.5. На прощание
- •Приложение а. Глоссарий
- •Приложение в. Объяснение нотации
- •В.1. Диаграмма классов
- •В.2. Диаграмма объектов
- •В.3. Диаграмма взаимодействий
- •Приложение с. Базовые классы
- •Библиография
- •Алфавитный указатель
Паттерн команда
Команды Lexi – это пример применения паттерна команда, описывающего, как инкапсулировать запрос. Этот паттерн предписывает единообразный интерфейс для выдачи запросов, с помощью которого можно сконфигурировать клиенты для обработки разных запросов. Интерфейс изолирует клиента от реализации запроса. Команда может полностью или частично делегировать реализацию запроса другим объектам либо выполнять данную операцию самостоятельно. Это идеальное решение для приложений типа Lexi, которые должны предоставлять централизованный доступ к функциональности, разбросанной по разным частям программы. Данный паттерн предлагает также механизмы отмены и повтора, надстроенные над базовым интерфейсом класса Command.
2.8. Проверка правописания и расстановка переносов
Наша последняя задача связана с анализом текста, точнее, с проверкой правописания и нахождением мест, где можно поставить перенос для улучшения форматирования.
Ограничения здесь аналогичны тем, о которых уже говорилось при обсуждении форматирования в разделе 2.3. Как и в случае с разбиением на строки, есть много способов реализовать поиск орфографических ошибок и вычисление точек переноса. Поэтому и здесь планировалась поддержка нескольких алгоритмов. Пользователь сможет выбрать тот алгоритм, который его больше устраивает по соотношению потребляемой памяти, скорости и качеству. Добавление новых алгоритмов тоже должно реализовываться просто.
Также мы хотим избежать жесткой привязки этой информации к структуре документа. В данном случае такая цель даже более важна, чем при форматировании, поскольку проверка правописания и расстановка переносов – это лишь два вида анализа текста, которые Lexi мог бы поддерживать. Со временем мы собираемся расширить аналитические возможности Lexi. Мы могли бы добавить поиск, подсчет слов, средства вычислений для суммирования значений в таблице, проверку грамматики и т.д. Но мы не хотим изменять класс Glyph и все его подклассы при каждом добавлении такого рода функциональности.
У этой задачи есть две стороны: доступ к анализируемой информации, которая разбросана по разным глифам в структуре документа и собственно выполнение анализа. Рассмотрим их по отдельности.
Доступ к распределенной информации
Для многих видов анализа необходимо рассматривать текст посимвольно. Но анализируемый текст рассеян по иерархии структур, состоящих из объектов-глифов. Чтобы исследовать текст, представленный в таком виде, нужен механизм доступа, знающий о структурах данных, в которых хранится текст. Для некоторых глифов потомки могут храниться в связанных списках, для других – в массивах, а для третьих и вовсе используются какие-то экзотические структуры. Наш механизм доступа должен справляться со всем этим.
К сожалению, для разных видов анализа методы доступа к информации могут различаться. Обычно текст сканируется от начала к концу. Но иногда требуется сделать прямо противоположное. Например, для реверсивного поиска нужно проходить по тексту в обратном, а не в прямом направлении. А при вычислении алгебраических выражений необходим внутренний порядок обхода.
Итак, наш механизм доступа должен уметь приспосабливаться к разным структурам данных и поддерживать разные способы обхода.