Когда программисты говорят о шаблонах проектирования, они обычно говорят об установленных и повторно используемых конструкциях или архитектурах, которые решают конкретные проблемы. По большей части шаблоны проектирования определяются независимо от языков программирования. Если вы новичок в программировании, вы, вероятно, все еще не понимаете, о чем я говорю. В любом случае, вы, вероятно, использовали шаблон дизайна в какой-то момент, даже не подозревая об этом. Далее я представляю пять шаблонов проектирования, о которых должен знать каждый инженер-программист.
Оглавление:
- Кто создает и кто использует шаблоны проектирования?
- Шаблон “Одиночка” (Singleton, Синглтон)
- Шаблон “Фасад” (Facade)
- Шаблон “Адаптер” (Adapter)
- Шаблон “Внедрение зависимости” (Dependency Injection)
- Что еще почитать про шаблоны проектирования
Кто создает и кто использует шаблоны проектирования?
Что ж, каждый может создать. Если мы вкратце взглянем на историю шаблонов проектирования, мы обнаружим, что они восходят к Кристоферу Александру, архитектору, который написал статьи и книги, такие как «Узор улиц» или «Язык шаблонов», в которых он говорит об актуальных архитектурных решениях, материалах и инструментах.
В основе […] лежит идея, что люди должны проектировать свои дома, улицы и сообщества. Эта идея […] исходит из наблюдения, что большинство чудесных мест в мире были созданы не архитекторами, а людьми — Кристофер Александр и др., «Язык шаблонов»
На мой взгляд, это очень подходящая метафора, потому что каждый может определить шаблон дизайна, даже если это обычно делают более опытные разработчики. Вы ожидаете, что опытный архитектор программного обеспечения создаст очень сложные шаблоны проектирования, однако каждый разработчик находится в уникальной ситуации и сталкивается с проблемами, требующими индивидуальных решений. Не каждую проблему нужно решать с помощью шаблона проектирования, но опытный инженер-программист признает хорошую возможность.
Если вы относительный новичок в программировании, вы, вероятно, не начнете определять шаблоны проектирования после создания некоторых «Hello World». Более вероятно, что вы начнете получать опыт, изучая и «употребляя» определенные фреймворки, такие как Vue, Angular или ASP. И пока вы будете это делать, вы, вероятно, узнаете о шаблонах проектирования. Когда вы будете подниматься по лестнице технологического мастерства, вы будете узнавать еще больше, пока в какой-то момент вы не перестанете использовать только технологические фреймворки и шаблоны проектирования, но также начнете создавать свои собственные.
Но хватит вступления. Давайте перейдем к моему списку из пяти шаблонов проектирования, которые необходимо знать разработчикам программного обеспечения.
Шаблон “Одиночка” (Singleton, Синглтон)
Синглтон — очевидный выбор и, вероятно, встречается в каждом списке шаблонов проектирования. И для этого есть веские причины: его относительно легко понять, он используется во многих проектах и является неотъемлемой частью других шаблонов проектирования. Популярные примеры применения Singleton включают в себя драйверы баз данных и экземпляры логеров. Синглтон гарантирует, что существует только один экземпляр класса. В следующем фрагменте кода показано, как создать синглтон (C #):
Статический экземпляр метода доступа гарантирует, что будет создан новый экземпляр класса, если он еще не существует. В противном случае он возвращает уже созданный экземпляр. Поскольку он является общедоступным статическим средством доступа, к одному и тому же экземпляру можно получить доступ из любой точки сборки.
Но почему вам может понадобиться только один экземпляр?
Приведенный ранее пример драйвера базы данных на самом деле является устаревшим, потому что вам следует применять некий шаблон параллелизма, а не синглтон. В этом случае синглтон будет так называемым «анти-шаблоном». Как упоминалось ранее, синглтоны часто являются частью других шаблонов проектирования, таких как шаблон Строителя, Фабрики или Прототипа, которые существуют для создания экземпляров объектов, потому что, например, им могут потребоваться глобальные конфигурации для инициализации, и эти конфигурации и свойства должны поддерживаться единичный экземпляр любой ценой. Еще одно преимущество синглтона — ленивая инициализация — помните, что объект будет создан при первом доступе.
Шаблон “Фасад” (Facade)
Паттерн Фасад указывает на связь с реальной архитектурой, имитируя видимый фасад здания. Вы видите только то, что видно спереди, но не видите, что находится внутри — комнаты, интерьер, электричество и так далее. С технической точки зрения: фасад — это открытый интерфейс для сложной системы, скрытой от пользователя. Если хотите, это упрощает сложную систему. Фасады обычно используются в объектно-ориентированных языках программирования.
Основываясь на примере архитектуры: представьте, что у вас есть система, состоящая из двух компонентов — компонентов «Жилье» и «Жилой дом». Эти компоненты необходимы вам для организации вечеринки, которая может выглядеть следующим образом.
Фасад для планирования вечеринки будет использовать компоненты соответствующим образом и упростит сложную систему.
Фасад хочет, чтобы вы только начали вечеринку или остановили ее. Вам не нужно беспокоиться о уборке, приготовлении пищи или покупках. С другой стороны, IPartyFacade не позволяет добавлять другие напитки в список. Вы жертвуете гибкостью ради удобства.
Шаблон “Адаптер” (Adapter)
Шаблон адаптера используется, когда у вас есть компонент, который вы хотите интегрировать в среду, которая изначально не предназначалась для использования данным образом. Чтобы проиллюстрировать этот пример, предположим, что у нас есть система, которая отвечает за зарядку мобильных телефонов. До сих пор это работало только с iPhone. Теперь вы добавляете телефоны Android, которые также нуждаются в зарядке, но вы не можете использовать зарядное устройство iPhone из-за проблем несовместимости. Ваш адаптер будет PhoneAdapter, реализующим как iPhone, так и Android Phone, который сможет различать оба телефона и предоставить вам правильный метод зарядки.
Шаблон “Декоратор” (Decorator)
Этот шаблон проектирования динамически расширяет базовый класс с помощью функций, которых нет в базовом классе, не затрагивая реализации базовых классов. Это может показаться довольно абстрактным, поэтому для пояснения взгляните на следующий пример:
Абстрактный класс HouseAccessories украшает IHouse и обеспечивает дополнительную функциональность. В методе SellHouse мы используем базовый AtticHouse и расширяем его, добавляя MultiStoryPackage, а также CustomPaintingPackage. Полученный результат будет такой:
House: House with attic + Multi Story Package + Custom Painting Package Cost: 36000 Дом: Дом с мансардой + многоэтажный пакет + индивидуальная покраска Стоимость пакета: 36000
Шаблон “Внедрение зависимости” (Dependency Injection)
Последний шаблон проектирования в моем списке — внедрение зависимостей. Этот вариант проще, чем кажется на первый взгляд, но, по моему опыту, он имеет тенденцию сбивать с толку начинающих программистов. Идея состоит в том, чтобы уменьшить проблемы, отделив создание объекта от его использования. Это может повысить удобочитаемость и возможность повторного использования кода, но, с другой стороны, обеспечивает определенный уровень сложности — разработчикам приходится перемещаться по большему количеству классов, в IDE могут возникать проблемы с разрешением ссылок, а также нужны дополнительные предварительные усилия по реализации и настройке зависимостей.
Как видите, зависимость определяется интерфейсом, а не классом реализации. Это может быть какой-то класс регистратора, но на самом деле ему не нужно знать. Единственное, что должен знать использующий класс, это то, что у зависимости есть функция с именем Write, чтобы иметь возможность ее использовать. Однако инфраструктура внедрения зависимостей должна знать, какую реализацию использовать. В следующем кратком примере ASP.NET Core показано, как удовлетворить это требование:
Что еще почитать про шаблоны проектирования
Как было сказано в начале статьи, существует множество шаблонов проектирования, и многие из них, такие как шаблон Стратегия или Хранитель, заслуживают внимания.
Если вам интересно копнуть глубже, я рекомендую книгу «Паттерны проектирования. Повторно используемые элементы объектно-ориентированного программного обеспечения» Эриха Гаммы и других.
Дополнительно: