Programming Taskbook


E-mail:

Пароль:

Регистрация пользователя   Восстановление пароля

 

ЮФУ

Электронный задачник по программированию

©  М. Э. Абрамян (Южный федеральный университет), 1998–2022

 

PT for OOP | Общее описание

Next


Приемы объектно-ориентированного проектирования

Скачать дистрибутив электронного задачника Programming Taskbook for OOP (русская версия 1.0)


Общее описание

Программный комплекс «Электронный задачник по паттернам проектирования Programming Taskbook for OOP» (PT for OOP) содержит дополнительные компоненты электронного задачника Programming Taskbook, предназначенные для изучения классических паттернов проектирования, описанных в книге Гамма Э., Хелм Р., Джонсон Р., Влиссидес Дж. Приемы объектно-ориентированного проектирования. Паттерны проектирования (издание на русском языке: СПб.: Питер, 2015. — 368 с.). В дальнейшем ссылки на эту книгу будут даваться в виде GoF («Gang of Four», как часто назвают команду ее авторов).

Для возможности использования данного комплекса его следует установить в системный каталог базового варианта электронного задачника Programming Taskbook версии не ниже 4.22 (обычно системным каталогом задачника является каталог C:\Program Files\PT4).

Задания могут выполняться на любых языках и в любых программных средах, поддерживаемых электронным задачником Programming Taskbook.

Комплекс PT for OOP является свободно распространяемым программным продуктом (freeware); он может использоваться как с полным вариантом задачника PT4Complete, так и со свободно распространяемым мини-вариантом PT4Mini.

Версия 1.0 задачника PT for OOP включает 44 задания. Начальные 6 заданий, входящие во вводную группу OOP0Begin, посвящены базовым принципам и дополнительным приемам объектно-ориентированного программирования:

  • Поля и методы класса. Инкапсуляция (OOP0Begin1)
  • Наследование (OOP0Begin2)
  • Полиморфизм (OOP0Begin3)
  • Получение информации о типе времени выполнения (OOP0Begin4)
  • Генерация и обработка исключений (OOP0Begin5)
  • Шаблоны функций и шаблоны классов (OOP0Begin6)

В последующих 38 заданиях рассматривается 21 классический паттерн (из 23, описанных в книге GoF). С учетом классификации паттернов, принятой в этой книге, эти задания разбиты на три группы:

  • OOP1Creat (10 заданий, связанных с 5 порождающими паттернами)
  • OOP2Struc (11 заданий, связанных с 6 структурными паттернами)
  • OOP3Behav (17 заданий, связанных с 10 паттернами поведения)

В пределах каждой группы задания распределены в соответствии с частотой использования изучаемых паттернов; кроме того, первыми в каждой группе рассматриваются наиболее простые и распространенные паттерны, выделенные авторами книги GoF в особое подмножество. Информация о частоте использования паттернов взята из книги Шевчук А., Охрименко Д., Касьянов А. Design Patterns via C#. Приемы объектно-ориентированного проектирования — 2015. Электронное издание. — 288 с. Также принималась во внимание степень детализации, с которой паттерны описывались в книге Фримен Э., Робсон Э., Сьерра К., Бейтс Б. Head First. Паттерны проектирования. — СПб.: Питер, 2018. — 656 с.

Ниже приводится список паттернов, упорядоченный по номерам связанных с ними учебных заданий. В квадратных скобках указывается частота использования паттерна (по шкале от 1 — «низкая частота использования» до 5 — «высокая частота»); если паттерн относится к особой группе простых и распространенных паттернов, выделенной в книге GoF, это отмечается символом «*»; если паттерну была посвящена отдельная глава в книге «Head First. Паттерны проектирования», это отмечается символом «+» (если символ «+» отсутствует, то это означает, что паттерн лишь кратко упомянут в последней главе этой книги). После информации, приводимой в квадратных скобках, указываются номера заданий, связанных с данным паттерном.

Порождающие паттерны (группа OOP1Creat)

Подгруппа 1

Подгруппа 2

Структурные паттерны (группа OOP2Struc)

Подгруппа 1

  • Adapter (Адаптер) [4*+] 1, 2, 3, 4
  • Composite (Компоновщик) [4*+] 5, 6
  • Decorator (Декоратор) [3*+] 7, 8

Подгруппа 2

  • Proxy (Заместитель) [4+] 9
  • Bridge (Мост) [3] 10
  • Flyweight (Приспособленец) [1] 11

Паттерны поведения (группа OOP3Behav)

Подгруппа 1

Подгруппа 2

  • Iterator (Итератор) [5+] 7
  • Command (Команда) [4+] 8, 9
  • State (Состояние) [3+] 10. 11

Подгруппа 3

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

Завершающая подгруппа содержит редко используемые и при этом, как правило, сложные паттерны. Средняя подгруппа группы OOP3Behav занимает промежуточное положение: она включает три достаточно часто используемых и популярных паттерна, каждому из которых посвящена глава в книге «Head First. Паттерны проектирования», хотя они и не входят в выделенную группу простых и распространенных паттернов из книги GoF.

Паттерны, не включенные в задачник

Вне рассмотрения оказались следующие два паттерна, описанные в книге GoF:

  • Facade (Фасад) [5+] (структурный паттерн)
  • Memento (Хранитель) [1] (паттерн поведения)

Причина исключения из рассмотрения широко распространенного паттерна Facade связана со спецификой его применения как простой «надстройки» над сложной системой классов, в которой весьма расплывчато определяются роли участников. Таким образом, без использования сколько-нибудь сложной системы классов продемонстрировать нетривиальное применение паттерна Facade не удается.

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

Особенности заданий, связанных с изучением паттернов

При разработке учебных заданий были использованы дополнительные возможности электронного задачника Programming Taskbook последних версий. В частности, с первым заданием, посвященным новому паттерну, связывается рисунок с диаграммой классов (взятый из английского варианта книги GoF). Этот рисунок отображается рядом с окном задачника, а также включается в html-описание задания (для отображения на экране html-описания задания достаточно щелкнуть в окне задачника на метке Режим или нажать клавишу F4).

Для языков C++, C#, Java, Python и Ruby с каждым заданием связана особая программа-заготовка, которая содержит фрагменты описания некоторых классов, требующихся для выполнения задания. В разделах с формулировками заданий (группы OOP0Begin, OOP1Creat, OOP2Struc, OOP3Behav) приведены тексты заготовок для всех этих языков.

Чтобы наглядно выявить взаимосвязи между классами, реализуемые в рамках того или иного паттерна, достаточно рассмотреть сравнительно простые классы, содержащие небольшой набор числовых или строковых полей и выполняющие простые действия по их обработке. Простота описанных в задаче классов нередко приводит к тому, что для такой задачи можно легко написать программу, которая будет правильно преобразовывать исходные данные в результирующие, не применяя методы объектно-ориентированного программирования. При этом может возникнуть ощущение, что использование паттерна лишь усложняет решение поставленной задачи. Однако необходимо учитывать, что сравнительная простота требуемого в задачах преобразования исходных данных обусловлена лишь необходимостью сосредоточить внимание на ключевых особенностях того или иного паттерна, и главной целью при выполнении задания является не получение «максимально быстрым способом» правильного набора результатов, а реализация правильно функционирующей системы классов, связанной с изучаемым паттерном. Роль задачника состоит в упрощении действий по вводу и выводу данных и автоматической проверке полученных результатов (правильность которых должна служить подтверждением правильности разработанной системы классов).

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

В начале первого задания для каждого паттерна приводятся связанные с ним общие сведения: варианты наименования, частота использования, назначение, а также участники и их роли в реализации паттерна. Эта информация в основном взята из книги GoF.

Для 13 паттернов (в частности, для всех паттернов, включенных в первую подгруппу каждой группы) предусмотрено более одного задания (обычно два). Второе задание уже не сопровождается диаграммой классов; в нем, как правило, используются названия классов и их членов, соответствующие не общему описанию паттерна, а специфике рассматриваемой задачи. Во втором задании обычно делается попытка проиллюстрировать применение изучаемого паттерна к конкретной (хотя и простой) задаче с реальным наполнением (в то время как в первом задании обычно описывается формальная система классов с несколько надуманной схемой взаимодействия, которая, тем не менее, наглядно демонстрирует ключевые особенности изучаемого паттерна). Ниже приводятся примеры таких «конкретных вторых заданий», многие идеи для которых заимствованы из упомянутых выше книг:

  • формирование зоопарка из животных определенной группы (OOP1Creat3 — третье задание для паттерна Factory Method);
  • конструирование набора элементов управления, оформленных в различном стиле (OOP1Creat5 — второе задание для паттерна Abstract Factory);
  • клонирование графических примитивов (OOP1Creat8 — второе задание для паттерна Prototype);
  • генерация идентификаторов по их строковым описаниям с применением соглашений, принятых для различных языков программирования (OOP1Creat10 — второе задание для паттерна Builder);
  • адаптация интерфейса класса, описывающего текстовый объект, к интерфейсу графических объектов (OOP2Struc3 и OOP2Struc4 — третье и четвертое задание для паттерна Adapter);
  • вычисление суммарной стоимости сложных устройств, состоящих из иерархически организованных компонентов (OOP2Struc6 — второе задание для паттерна Composite);
  • построение суперпозиций различных функций и вычисление их значений (OOP2Struc8 — второе задание для паттерна Decorator);
  • реализация набора классов-валидаторов и их использование для проверки правильности набора текстовых данных (OOP3Behav4 — второе задание для паттерна Strategy);
  • реализация алгоритмов поиска минимумов и максимумов в наборе при применении различных правил сравнения элементов (OOP3Behav6 — второе задание для паттерна Template Method);
  • реализация макрокоманд и системы отмены и восстановления предыдущих операций (OOP3Behav9 — второе задание для паттерна Command);
  • моделирование работы автомата по продаже шариков (OOP3Behav11 — второе задание для паттерна State);
  • конструирование символьной строки на основе грамматики, включающей условные и циклические конструкции (OOP3Behav17 — второе задание для паттерна Interpreter).

Следует заметить, что «первые задания» для паттернов State и Interpreter (OOP3Behav10 и OOP3Behav16) также могут быть отнесены к конкретным заданиям, поскольку в первом из них реализуется строковый парсер, распознающий ряд токенов, а во втором — грамматика, связанная с вычислением арифметического выражения.

Случаев, когда «вторые задания» не связаны с конкретной задачей, немного: это OOP3Behav2 — второе задание для паттерна Observer и OOP3Behav14 — второе задание для паттерна Chain of Responsibility. В этих заданиях используются те же формальные наборы классов, что и в соответствующих первых заданиях, однако рассматриваются важные дополнительные модификации паттерна.

Если с паттерном связано единственное задание, то, как правило, в нем описывается формальная система классов, не связанная с конкретной предметной областью и решающая условную задачу по обработке числовых или строковых данных. Однако среди них тоже можно отметить задания с реальным содержанием: это реализация виртуального и защищающего заместителя в OOP2Struc9 — задании для паттерна Proxy и генерация различных вариантов заголовков в OOP2Struc10 — задании для паттерна Bridge.

С двумя паттернами связано более двух заданий: это Factory Method — первый паттерн из группы OOP1Creat, для которого имеются три задания, и Adapter — первый паттерн из группы OOP2Struc, для которого имеются четыре задания.

Второе задание для паттерна Factory Method представляет собой модификацию первого задания, в которой демонстрируется вариант реализации паттерна, не использующий абстрактные классы (в то время как третье задание, уже упоминавшееся выше, является «конкретным» заданием, связанным с генерацией различных зоопарков).

Наличие четырех заданий для паттерна Adapter объясняется тем, что фактически имеется два варианта этого паттерна: первый вариант называется адаптером объекта и основан на включении адаптируемого объекта в класс-адаптер в виде ссылочного поля, второй вариант называется адаптером класса и основан на множественном наследовании (или на наследовании с дополнительным подключением интерфейсов). Задания OOP2Struc1 и OOP2Struc2 являются «первыми» заданиями на ознакомление с адаптером объекта и адаптером класса соответственно, а задания OOP2Struc3 и OOP2Struc4 являются «вторыми» заданиями, связанными с этими вариантами адаптеров и имеющими реальное содержание.

Некоторые проблемы вызвал паттерн Singleton, поскольку связанная с ним система классов является крайне простой (она состоит из единственного класса Singleton). Чтобы сделать соответствующее задание (OOP1Creat6) более содержательным, было решено дополнительно описать варианты паттерна для создания ограниченного количества объектов (о таких вариантах кратко упоминается в книге GoF). Хотя подобные варианты являются не слишком полезными (по сравнению с самим паттерном Singleton), они дают возможность более детально разобраться в особенностях данного паттерна.

Паттерн Iterator интересен тем, что в большинстве современных языков он реализован на уровне стандартных библиотек или даже на уровне языковых конструкций. Тем не менее, в подгруппу 2 группы OOP3Behav включено одно задание, посвященное этому паттерну (OOP3Behav7). В задании рассматривается вариант реализации нестандартного итератора и приводится замечание о том, что при выполнении задания можно использовать как базовые объектно-ориентированные возможности языка, так и средства из его библиотек, предназначенные для создания итераторов и работы с ними.


Next

 

Рейтинг@Mail.ru

Разработка сайта:
М. Э. Абрамян, В. Н. Брагилевский

Последнее обновление:
19.04.2022