Что такое паттерны в java
Перейти к содержимому

Что такое паттерны в java

  • автор:

Паттерны проектирования

Данной статьей мы начинаем серию статей, посвященных паттернам проектирования.

Статьи рассчитаны на тех, кто уже хорошо знает ООП.

Что такое паттерны в программировании

Ну, что ж, давайте сначала разберемся что такое паттерн. А затем плавно перейдем к такому понятию как «паттерны в программировании».

Паттерн — это повторяющийся элемент в различных сферах жизни.

Пример 1: окрас тигра — это паттерн.

Пример 2: Коробка передач — это паттерн.

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

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

Шаблон проектирования / шаблон программирования / паттерн — это типичные способы решения часто возникающих задач в сфере разработки ПО.

ВАЖНО:

Паттерн — это не готовое решение, которое можно откуда-то скопировать и вставить в Вашу программу. Это только общие принципы, которые надо уметь правильно применить.

Мне надо знать паттерны?

  • Паттерны очень часто применяются на практике. Конечно, для начинающих программистов понимание паттернов не всегда заходит легко. Так что наберитесь терпения и учим, учим, учим.
  • Паттерны часто спрашивают на собеседованиях.
  • И самое главное — паттерны предлагают Вам готовые решения. Они помогут Вам сохранить время и усилия, а качество программы повысится.

Откуда они взялись

Хотя сама идея паттернов далеко не новая, популярной она стала после выхода книги «Приёмы объектно-ориентированного проектирования. Паттерны проектирования«. Это произошло в 1994 году. С тех пор мир захватила «шаблономания» ��

Какие они бывают

Есть основные три категории паттернов:

  • Порождающие (Creational Design Patterns)

Эти шаблоны что-то создают. Например, «как создать объект, который нельзя изменить»? «Как создать класс, который будет создавать новые объекты других классов?»?

  • Структурные (Structural Design Patterns)

Отвечают за иерархию классов и интерфейсов. Например, «как заставить объекты с несовместимыми интерфейсами работа вместе»?

  • Поведенческие (Behavioral Design Patterns)

Помогает добиться нужного поведения от объектов. Например, «как сделать так, чтобы объекты одного класса следили за изменениями в других классах и реагировали на них»?

Из чего состоит паттерн?

  • Имя
  • Задача, которую решает паттерн
  • Решение:
    • Структуры классов, составляющих решение;
    • Примера на одном из языков программирования;

    А конкретнее?

    Существует 23 классических шаблона проектирования, с которых все и началось. В настоящий момент паттернов намного больше — минимум в 2-3 раза больше.

    Здесь о каждом из них мы, конечно, говорить не будем — это много �� Но мы расскажем об основных паттернах в будущих статьях.

    Самыми-самыми «базовыми» шаблонами проектирования можно назвать следующие:

    С них можно начинать изучение паттернов. Ниже в этой статье Вы найдете ссылочки на статьи по этим паттернам.

    Что следует знать

    Одинаковые ли шаблоны для всех языков программирования?

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

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

    Да, конечно. Останется только всем о нем рассказать ��

    Это все, что мы хотели Вам рассказать в данной статье.

    Статьи, посвященные конкретным паттернам, Вы найдете по этим ссылочкам:

    • Паттерн Singleton — Часть 1
    • Паттерн Singleton — Часть 2
    • Паттерн Builder
    • Паттерн Factory — Часть 1

    Надеемся, наша статья была Вам полезна. Также есть возможность записаться на наши курсы. Детальнее у на сайте.

    • ← Правила наследования в Java
    • Методы в Java →

    Что такое паттерны в java

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

    • нарисовать флагшток
    • нарисовать первую полосу белого цвета
    • нарисовать вторую полосу синего цвета
    • нарисовать третью полосу красного цвета

    1. Идем напролом
    Затея выглядит просто:

     class Main < public static void main(String[] args) < System.out.println("Рисуем флаг России:"); System.out.println("Флагшток нарисован"); System.out.println("Полоса белого цвета нарисована"); System.out.println("Полоса синего цвета нарисована"); System.out.println("Полоса красного цвета нарисована"); >> 

    Результат выполнения программы:

    Наша программа делает то, что требуется. Далее заказчик попросил написать код для рисования еще одного трехцветного флага — флага Нидерландов.

    Добавим несколько строк кода:

     class Main < public static void main(String[] args) < System.out.println("Рисуем флаг России:"); System.out.println("Флагшток нарисован"); System.out.println("Полоса белого цвета нарисована"); System.out.println("Полоса синего цвета нарисована"); System.out.println("Полоса красного цвета нарисована"); System.out.println("\nРисуем флаг Нидерландов:"); System.out.println("Флагшток нарисован"); System.out.println("Полоса красного цвета нарисована"); System.out.println("Полоса белого цвета нарисована"); System.out.println("Полоса синего цвета нарисована"); >> 

    Результат выполнения программы:

    Мы выполнили и это задание — программа рисует необходимые заказчику флаги.

    Но, наш код ужасен! Мы не используем объектно-ориентированный подход, и у нас нарушен DRY-принцип — код дублируется.

    2. Используем ООП

    Давайте создадим для каждого флага свой класс: RussianFlag и NetherlandsFlag. Рисование конкретным цветом вынесем в методы, которые поместим в класс Colors, что позволит избавиться от дублирования кода.

    Методы рисования красками сделаем статическими (чтобы не создавать экземпляр):

     class Colors < static void paintWhiteColor() < System.out.println("Полоса белого цвета нарисована"); >static void paintBlueColor() < System.out.println("Полоса синего цвета нарисована"); >static void paintRedColor() < System.out.println("Полоса красного цвета нарисована"); >> 

    Классы для рисования флага России и Нидерландов выглядят так:

     class RussianFlag < void drawFlag() < drawFlagpole(); Colors.paintWhiteColor(); Colors.paintBlueColor(); Colors.paintRedColor(); >private void drawFlagpole() < System.out.println("Флагшток нарисован"); >> 
     class NetherlandsFlag < void drawFlag() < drawFlagpole(); Colors.paintRedColor(); Colors.paintWhiteColor(); Colors.paintBlueColor(); >private void drawFlagpole() < System.out.println("Флагшток нарисован"); >> 

    Класс Main теперь выглядит так:

     class Main < public static void main(String[] args) < System.out.println("Рисуем флаг России:"); RussianFlag russianFlag = new RussianFlag(); russianFlag.drawFlag(); System.out.println("\nРисуем флаг Нидерландов:"); NetherlandsFlag netherlandsFlag = new NetherlandsFlag(); netherlandsFlag.drawFlag(); >> 

    Запустив это код, мы получим тот же самый результат, что и ранее — будут нарисованы два флага.

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

    Класс Flagpole выглядит так:

     class Flagpole < static void drawFlagpole() < System.out.println("Флагшток нарисован"); >> 

    Внесем изменения в классы RussianFlag и NetherlandsFlag: добавим extends Flagpole и уберем метод drawFlagpole:

     class RussianFlag extends Flagpole < void drawFlag() < drawFlagpole(); Colors.paintWhiteColor(); Colors.paintBlueColor(); Colors.paintRedColor(); >> 
     class NetherlandsFlag extends Flagpole < void drawFlag() < drawFlagpole(); Colors.paintRedColor(); Colors.paintWhiteColor(); Colors.paintBlueColor(); >> 

    Снова запустив класс Main, мы получим тот же самый результат — два требуемых флага.
    3. Реализуем Шаблонный метод

    Внезапно мы понимаем, что каждый раз действуем по одному и тому же алгоритму: рисуем флагшток, верхнюю часть флага, среднюю и нижнюю. Этот алгоритм неизменен для рисования флагов с тремя полосами. А что, если нам сделать методы для рисования полос флага абстрактными, а их реализацию делегировать (поручить) классам конкретных флагов? И даже сам алгоритм рисования флага поместить в абстрактный класс в метод drawFlag. А что бы его нельзя было переопределить (изменить) при наследовании, пометить его как final.

    Класс Flagpole становится ненужным, поскольку рисование флагштока также можно перенести в абстрактный класс. Итак, класс AbstractThreeRowsFlag будет выглядеть следующим образом:

     abstract class AbstractThreeRowsFlag < abstract void drawUpperLevel(); abstract void drawMiddleLevel(); abstract void drawBottomLevel(); final void drawFlag() < drawFlagpole(); drawUpperLevel(); drawMiddleLevel(); drawBottomLevel(); >private void drawFlagpole() < System.out.println("Флагшток нарисован"); >> 

    Метод drawFlag(), содержащий алгоритм рисования флага, является шаблонным методом. Он так называется потому, что задает скелет в виде последовательности шагов, которые будут переопределять (реализовывать), каждый по своему, наследники AbstractThreeRowsFlag. Его подклассы не смогут изменить последовательность шагов, т.к. шаблонный метод помечен, как final и не наследуется.

    Как вы уже поняли, для рисования флагов мы только что использовали паттерн под названием «Шаблонный метод» (Template Method), благодаря которому мы избавились от дублирования кода, а так же повысили его универсальность и переиспользуемость.

    Обратите внимание, не все методы в шаблонном методе являются абстрактными, например drawFlagpole (рисование флагштока). Из этого можно сделать вывод, что шаблонный метод не обязательно должен состоять только из абстрактных методов, которые необходимо переопределять в подклассах. Он может содержать переменные, какую-то внутреннюю логику и т. д. Но очень часто новички, читая материал по данному паттерну, ошибочно полагают, что шаблонный метод — это метод, который состоит только из абстрактных методов и ничего другого содержать не может. Это и не удивительно, в интернете полно статей с примерами таких методов, что сбивает с толку.

    Вернемся к нашим флагам, классы для рисования которых уже выглядят так (про @Override можно прочитать в нашей прошлой статье):

     class RussianFlag extends AbstractThreeRowsFlag < @Override void drawUpperLevel() < Colors.paintWhiteColor(); >@Override void drawMiddleLevel() < Colors.paintBlueColor(); >@Override void drawBottomLevel() < Colors.paintRedColor(); >> 
     class NetherlandsFlag extends AbstractThreeRowsFlag < @Override void drawUpperLevel() < Colors.paintRedColor(); >@Override void drawMiddleLevel() < Colors.paintWhiteColor(); >@Override void drawBottomLevel() < Colors.paintBlueColor(); >> 

    Класс Main теперь выглядит так:

     class Main < public static void main(String[] args) < System.out.println("Рисуем флаг России:"); AbstractThreeRowsFlag russianFlag = new RussianFlag(); russianFlag.drawFlag(); System.out.println("\nРисуем флаг Нидерландов:"); AbstractThreeRowsFlag netherlandsFlag = new NetherlandsFlag(); netherlandsFlag.drawFlag(); >> 

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

    Какие существуют паттерны проектирования на Java

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

    Алексей Кодов
    Автор статьи
    7 июня 2023 в 16:12

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

    1. Порождающие паттерны

    Эти паттерны относятся к процессу создания объектов. Они обеспечивают гибкость и повторное использование кода при создании объектов. Вот некоторые из них:

    • Singleton ��: Обеспечивает создание только одного экземпляра класса и предоставление глобальной точки доступа к этому экземпляру.
    • Фабричный метод ��: Определяет интерфейс для создания объектов, позволяя подклассам выбирать, какой класс инстанциировать.
    • Абстрактная фабрика ��: Предоставляет интерфейс для создания семейств взаимосвязанных объектов без указания их конкретных классов.
    • Прототип ��: Позволяет создавать новые объекты путем копирования существующих объектов (прототипов), вместо создания новых объектов с нуля.

    2. Структурные паттерны

    Структурные паттерны определяют отношения между классами и объектами, создавая более сложные структуры. Вот некоторые из них:

    • Адаптер ��: Позволяет объектам с несовместимыми интерфейсами работать вместе.
    • Мост ��: Разделяет абстракцию и реализацию, так что они могут развиваться независимо друг от друга.
    • Компоновщик ��: Объединяет объекты в древовидные структуры для представления иерархии частей-целого.
    • Декоратор ��: Добавляет новые функции к существующему объекту без изменения его структуры.

    3. Поведенческие паттерны

    Поведенческие паттерны определяют обязанности и взаимодействие между объектами. Вот некоторые из них:

    • Цепочка обязанностей ⛓️: Позволяет передавать запросы по цепочке обработчиков, пока один из них не обработает запрос.
    • Команда ��: Инкапсулирует запрос в виде объекта, что позволяет параметризовать клиентов с различными запросами.
    • Итератор ��: Предоставляет способ последовательного доступа к элементам объекта-агрегата без раскрытия его внутренней структуры.
    • Наблюдатель ��: Определяет отношение «один-ко-многим» между объектами, так что при изменении состояния одного объекта автоматически уведомляются все зависимые объекты.

    Java-разработчик: новая работа через 11 месяцев
    Получится, даже если у вас нет опыта в IT

    Заключение

    Это лишь краткий обзор паттернов проектирования, доступных в Java. Использование этих паттернов может помочь вам создавать более гибкие, модульные и повторно используемые системы. Чтобы освоить их, практика и опыт являются ключевыми факторами. Удачи в изучении паттернов проектирования!

    Что такое паттерны проектирования в Java

    Изучите паттерны проектирования в Java, их типы и примеры применения для создания гибких и масштабируемых систем!

    Алексей Кодов
    Автор статьи
    7 июня 2023 в 16:12

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

    В Java существует множество паттернов проектирования, которые можно разделить на три основных типа:

    1. Порождающие паттерны: Эти паттерны связаны с процессом создания объектов и обеспечивают гибкость и повторное использование кода. Примеры таких паттернов: Singleton, Factory Method, Abstract Factory, Builder, Prototype.
    2. Структурные паттерны: Они определяют способы композиции классов и объектов для создания новых структур. Примеры структурных паттернов: Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy.
    3. Поведенческие паттерны: Эти паттерны определяют взаимодействие между объектами и облегчают обмен информацией между ними. Примеры поведенческих паттернов: Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor.

    Java-разработчик: новая работа через 11 месяцев
    Получится, даже если у вас нет опыта в IT

    Примеры паттернов проектирования в Java

    Давайте рассмотрим некоторые популярные паттерны проектирования на примерах Java-кода.

    Singleton

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

    public class Singleton < private static Singleton instance; private Singleton() < >public static synchronized Singleton getInstance() < if (instance == null) < instance = new Singleton(); >return instance; > >

    Adapter

    Adapter — это структурный паттерн, который позволяет объектам с несовместимыми интерфейсами работать вместе.

    interface EuropeanPlug < void useEuropeanPlug(); >class BritishPlug < void useBritishPlug() < System.out.println("Using British plug"); >> class PlugAdapter implements EuropeanPlug < private BritishPlug britishPlug; public PlugAdapter(BritishPlug britishPlug) < this.britishPlug = britishPlug; >@Override public void useEuropeanPlug() < britishPlug.useBritishPlug(); >>

    Observer

    Observer — это поведенческий паттерн, который определяет отношение «один-ко-многим» между объектами. Когда один объект (субъект) изменяется, все зависимые объекты (наблюдатели) уведомляются об этом и автоматически обновляются.

    import java.util.ArrayList; import java.util.List; interface Observer < void update(String news); >class NewsChannel implements Observer < private String news; @Override public void update(String news) < this.news = news; System.out.println("News updated: " + news); >> class NewsAgency < private List<Observer> observers = new ArrayList<>(); public void addObserver(Observer observer) < observers.add(observer); >public void removeObserver(Observer observer) < observers.remove(observer); >public void notifyObservers(String news) < for (Observer observer : observers) < observer.update(news); >> >

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *