Введение в паттерны проектирования
Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy — урок 90 из 104.
Паттерны проектирования — это проверенные, многократно используемые решения распространенных проблем, возникающих при проектировании программного обеспечения. Это не тот код, который вы копируете напрямую — это шаблоны или чертежи, описывающие, как структурировать классы и объекты для элегантного решения конкретных задач.
Концепция была популяризирована «Бандой четырех» (GoF) в их книге 1994 года, в которой были каталогизированы 23 фундаментальных паттерна. Эти паттерны обычно группируются в три категории:
| Категория | Цель | Примеры |
|---|---|---|
| Порождающие | Механизмы создания объектов | Singleton, Factory, Builder |
| Структурные | Композиция классов и объектов | Adapter, Decorator, Composite |
| Поведенческие | Взаимодействие и распределение обязанностей между объектами | Observer, Strategy, Command |
Зачем изучать паттерны проектирования? Они обеспечивают общий язык общения между разработчиками — фраза «используй здесь Factory» мгновенно передает сложную идею. Они также помогают избежать повторного изобретения решений и делают ваш код более гибким и удобным в сопровождении.
В C++ паттерны проектирования используют возможности ООП, которые вы уже изучили: наследование, полиморфизм, абстрактные классы и шаблоны. В следующих уроках вы реализуете несколько основных паттернов и поймете, когда каждый из них является подходящим инструментом для решения задачи.
Задание
ЛегкоДавайте создадим простой классификатор паттернов, который продемонстрирует ваше понимание трех категорий паттернов проектирования. Вы создадите систему, которая принимает название паттерна и определяет, к какой категории он относится — Creational, Structural или Behavioral — вместе с кратким описанием назначения этой категории.
Вы организуете свой код в трех файлах:
PatternCategory.h: Определите абстрактный базовый класс с именемPatternCategory, который представляет категорию паттернов проектирования. Он должен иметь:- Чисто виртуальный метод
getName(), который возвращает название категории в виде строки - Чисто виртуальный метод
getPurpose(), который возвращает описание того, что делают паттерны в этой категории - Виртуальный деструктор
Затем создайте три производных класса, наследуемых от
PatternCategory:CreationalCategory— возвращает имя"Creational"и назначение"Object creation mechanisms"StructuralCategory— возвращает имя"Structural"и назначение"Class and object composition"BehavioralCategory— возвращает имя"Behavioral"и назначение"Object interaction and responsibility"
- Чисто виртуальный метод
PatternClassifier.h: Создайте классPatternClassifier, который может определить, к какой категории относится данный паттерн.Ваш классификатор должен иметь метод
classify, который принимает название паттерна (строку) и возвращает указатель на соответствующуюPatternCategory. Используйте умные указатели (std::unique_ptr) для управления памятью.Классификатор должен распознавать следующие паттерны:
- Creational:
Singleton,Factory,Builder - Structural:
Adapter,Decorator,Composite - Behavioral:
Observer,Strategy,Command
Если название паттерна не распознано, верните
nullptr.- Creational:
main.cpp: Считайте один входной параметр — название паттерна проектирования.Создайте
PatternClassifierи используйте его для классификации входного паттерна. Если паттерн распознан, выведите:[PatternName] is a [CategoryName] pattern Purpose: [CategoryPurpose]Если паттерн не распознан, выведите:
Unknown pattern: [PatternName]
Например, при вводе Singleton:
Singleton is a Creational pattern
Purpose: Object creation mechanismsПри вводе Observer:
Observer is a Behavioral pattern
Purpose: Object interaction and responsibilityПри вводе Proxy:
Unknown pattern: ProxyЭта задача закрепляет знания о трех категориях паттернов проектирования, одновременно практикуя наследование, полиморфизм и умные указатели — концепции, которые вы уже освоили. Многофайловая структура отражает то, как в реальных проектах организуются связанные классы.
Шпаргалка
Паттерны проектирования — это многократно используемые решения распространенных проблем проектирования программного обеспечения. Они служат шаблонами для структурирования классов и объектов, а не готовым кодом для копирования.
Паттерны проектирования делятся на три основные категории:
| Категория | Назначение | Примеры |
|---|---|---|
| Порождающие | Механизмы создания объектов | Singleton, Factory, Builder |
| Структурные | Композиция классов и объектов | Adapter, Decorator, Composite |
| Поведенческие | Взаимодействие и распределение обязанностей между объектами | Observer, Strategy, Command |
Преимущества паттернов проектирования:
- Обеспечивают общий словарь терминов для разработчиков
- Позволяют избежать «изобретения велосипеда» при решении типовых задач
- Делают код более гибким и удобным в сопровождении
В C++ паттерны проектирования используют возможности ООП, включая наследование, полиморфизм, абстрактные классы и шаблоны.
Попробуйте сами
#include <iostream>
#include <string>
#include "PatternClassifier.h"
int main() {
// Считать название паттерна
std::string patternName;
std::cin >> patternName;
// TODO: Создать экземпляр PatternClassifier
// TODO: Использовать классификатор для классификации входного паттерна
// TODO: Если паттерн распознан, вывести:
// "[PatternName] is a [CategoryName] pattern"
// "Purpose: [CategoryPurpose]"
// TODO: Если паттерн не распознан (nullptr), вывести:
// "Unknown pattern: [PatternName]"
return 0;
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыСборка и компиляция C++Заголовочные файлы и файлы исходного кодаПространства имен и область видимостиВведение в ООП на C++Классы и объектыУказатель 'this'Методы (функции-члены)Атрибуты (члены данных)Основы конструкторов и деструкторовИтоги — Простой калькулятор4Свойства классов
Члены экземпляра против статическихГеттеры и сеттерыКонстантные функции-членыКлючевое слово mutableСтатические методы и переменныеДружественные функции и классыИтоги — Менеджер банковских счетов7Наследование
Основы наследованияУровни доступа при наследованииПорядок вызова конструкторов и деструкторовПереопределение методовВиртуальные функции и VTableМножественное наследованиеВиртуальное наследованиеИтоги — Иерархия сотрудников10Обзор STL
Обзор и философия STLКонтейнеры STLИтераторыАлгоритмы STLФункторы и лямбда-выраженияИтоги: частота слов13Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonFactory и Abstract FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy2Управление памятью
Стек и кучаУказатели и ссылкиДинамическая память (new/delete)Умные указатели в C++RAII в C++Итоги — Менеджер динамического массива5Инкапсуляция
Спецификаторы доступа в C++Спецификаторы доступа: подробный разборСокрытие данныхStruct против ClassВложенные и внутренние классыИтоги — Система учета студентов8Полиморфизм
Полиморфизм компиляции и времени выполненияПерегрузка функцийВиртуальные функции: повторениеЧистые виртуальные функцииАбстрактные классыПроектирование интерфейсов на C++Dynamic Casting и RTTIИтоги: Калькулятор фигур11Продвинутые концепции ООП
Композиция против наследованияМиксины через CRTPИдиома PimplСтирание типовEnum Classes и строгая типизацияОбработка исключений в ООППользовательские иерархии исключений14Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикRAII как паттерн3Конструкторы и деструкторы
Конструктор по умолчаниюПараметризованный конструкторКонструктор копированияКонструктор перемещенияСписки инициализации конструктораДелегирующие конструкторыГлубокое погружение в деструкторыПравило трех / пяти / нуляПовторение — класс String6Перегрузка операторов
Введение в перегрузку операторовПерегрузка арифметических операторовПерегрузка операторов сравненияОператоры потоковПерегрузка оператора присваиванияПерегрузка операторов [] и ()Операторы преобразования типовИтоги — класс Matrix9Шаблоны
Шаблоны функцийШаблоны классовСпециализация шаблоновВариативные шаблоныОсновы SFINAE и Type TraitsИтоги — Обобщенный контейнер