Найти тему
Nuances of programming

Пять шаблонов проектирования, которые необходимо знать каждому разработчику

Оглавление

Источник: Nuances of Programming

Сложность процесса разработки ПО можно контролировать, только отслеживая с самого начала. Поэтому перед стартом разработки необходим этап проектирования.

Как архитектор, вы проектируете в настоящем, с осознанием прошлого и ради будущего, которое по существу неизвестно.  —  Норман Фостер

В программной инженерии шаблон проектирования программного обеспечения  —  это общее, многократно применяемое решение регулярно встречающейся проблемы в контексте проектирования приложения.

Как правило, шаблон проектирования  —  это шаблон решения проблемы, который применим во многих различных ситуациях. Это не законченный дизайн, который непосредственно преобразуется в код, а скорее фундамент, на котором мы основываем программное обеспечение.

С течением времени появляются новые шаблоны проектирования, а также новые вызовы и ограничения для уже существующих шаблонов. И есть несколько шаблонов, которые разработчик должен понимать и уметь использовать соответственно обстоятельствам.

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

1. Синглтон

Это наиболее распространенный и широко известный шаблон проектирования. Почти каждое приложение в одной или нескольких своих областях реализует синглтон.

Данный шаблон применяют, чтобы ограничить создание класса только одним объектом. Такое полезно, когда для координации действий в системе требуется только один объект.

Чтобы предотвратить создание экземпляра вне класса, класс должен объявить закрытый конструктор. Кроме того, нужно объявить статическое поле типа singleton .

Метод getInstance() в приведенном выше коде гарантирует, что во время выполнения будет создан только один экземпляр класса.

Предпочтительный сценарий

Такой сценарий, где должен существовать только один экземпляр класса (в том числе учитывая кэши, пулы потоков и реестры).

Ограничение

Метод getInstance() в этом шаблоне  —  не потокобезопасен и поэтому допускает многократную инициализацию. Можно ограничить это, сделав метод синхронизированным, но так замедлится выполнение.

2. Фабричный метод

Слово “фабрика” относится здесь к тому, что как обычная фабрика производит продукцию, так и фабрика программного обеспечения производит объекты. Но делает это по-другому, а именно вызывая фабричный метод вместо вызова конструктора конкретного класса.

Обычно создание объекта происходит следующим образом:

DemoClass demoClassObject = new DemoClass();

Проблема такого подхода в том, что код задействует объект конкретного класса DemoClass и становится зависим от реализации DemoClass . Нет ничего плохого в создании объектов через new , но это плотно связывает код с конкретным классом.

Проблема решается с помощью фабрики шаблонов, как показано ниже:

Если требуется конкретное уведомление, нужно только указать тип, и оно будет возвращено.

Если позже добавится новый тип уведомления  —  электронная почта, то он не потребует почти никаких изменений и не повлияет на реализацию класса. Это открывает возможность извлечь максимум из полиморфизма.

Предпочтительный сценарий

Ситуации, когда вам нужно больше контроля над созданием экземпляров, чем предоставляют конструкторы. Кроме того, фабрика пригодится там, где разработчик может не знать, какой тип применить в конструкторе, например, при программировании по базовому типу или интерфейсу.

Ограничение

Фабрика шаблонов может расширить общее число классов в системе. Каждый конкретный класс также требует конкретного класса создателя объекта, но этого можно избежать с помощью параметризованного метода фабрики.

3. Шаблон строителя

Как следует из названия, шаблон “Строитель” применяют для построения объектов. Иногда объекты бывают сложными, состоят из нескольких подобъектов или требуют сложного процесса конструирования.

В этом шаблоне сложный объект строится шаг за шагом, и последний шаг вернет объект. Процесс построения объекта должен быть общим, чтобы с его помощью выходило создать различные представления одного и того же объекта.

Приведенный ниже пример поможет разобраться лучше:

Здесь мы создали объект для класса Product с помощью шаблона “Строитель”.

Предпочтительный сценарий

Шаблон строителя очень похож на фабричный метод. Ключевое различие в том, что “Строитель” полезен, когда для построения объекта нужно пройти много шагов.

Ограничение

Количество строк кода увеличивается, по крайней мере, вдвое в шаблоне строителя, но усилия окупаются с точки зрения гибкости дизайна и гораздо более читаемого кода.

4. Шаблон адаптера

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

Как применяется адаптер:

  1. Клиент делает запрос к адаптеру, вызывая на нем метод с использованием целевого интерфейса.
  2. Адаптер преобразует этот запрос с помощью интерфейса адаптера.
  3. Клиент получает результаты вызова и не знает о присутствии адаптера.

В приведенном выше коде предположим, что есть птица, которая может издавать звуки  —  makeSound() , и у нас есть пластиковая игрушечная утка toyDuck , которая может квакать  —  squeak() . Теперь предположим, что наш клиент меняет требование и хочет, чтобы toyDuck сделал makeSound() ?

Простое решение  —  поменять класс реализации на новый класс адаптера и сказать клиенту передать экземпляр птицы (которая хочет squeak() ) этому классу.

Предпочтительный сценарий

В случае двух приложений, одно из которых выдает выходные данные в формате XML, а другое требует ввод JSON (или какого-то другого формата), для бесперебойного контакта между ними вам понадобится адаптер.

Ограничение

Адаптер не сочетается с подклассами Adaptee или Target.

5. Шаблон состояния

Этот шаблон помогает представить несколько состояний объекта. Предположим, у нас есть объект для класса “Радио”. Радио может находиться в двух состояниях: включенном или выключенном. Эти состояния и представлены шаблоном состояний.

В приложениях, которые работают в реальном времени, у объектов много состояний, и этот шаблон пригодится для уменьшения сложности системы.

Давайте разберемся в этом на примере с радио:

Приведенный пример демонстрирует различные состояния радио с шаблоном состояний.

Предпочтительный сценарий

Случай, когда нужно представить несколько состояний объекта, способного к внутренним изменения. Если обходиться без шаблона состояния, код становится негибким и слишком полагается на структуру if-else .

Ограничение

Шаблон состояния требует писать много кода. В зависимости от того, сколько различных методов перехода состояний определено и в каком количестве возможных состояний может находиться объект, потребуется десяток или более различных методов.

Заключение

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

Большинство приложений строятся на основе ограниченного числа шаблонов проектирования, которые слегка модифицируются, чтобы получать преимущества в конкретных сценариях.

Читайте также:

Читайте нас в Telegram , VK

Перевод статьи Shubham Pathania : “5 Design Patterns Every Software Developer Should Know”