Файл: Практикум для студентов, обучающихся по направлению подготовки 09. 03. 04 Программная инженерия.pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 30.11.2023

Просмотров: 175

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Thread.sleep(200);
} catch (InterruptedException e) { e.printStackTrace();
}
System.out.println("We run it");
}); executorService.submit(() -> System.out.println("Start"));
Сначала выведется «Start», а затем «We run it».
CompletableFuture
CompletableFuture – иной способ для использования асинхронности, предоставляет удобный интерфейс для запуска асинхронных задач, например, runAsync. Позволяет легко строить цепочки из задач (Изучите код
CompltetableFuture, и определите, создается ли для каждой задачи отдельный поток). Примеры кода с CompletableFuture:
CompletableFuture future =
CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture anotherFuture = future.thenApply((s) -> { try {
Thread.sleep(2000);
} catch (InterruptedException e) { e.printStackTrace();
} return s + " world";
});
System.out.println(anotherFuture.get(3, TimeUnit.SECONDS));
4.2. Задание
Реализовать собственную имплементацию
ExecutorService с единственным параметром конструктора – количеством потоков.

5. ПРАКТИЧЕСКАЯ РАБОТА № 5
Цель работы
Познакомиться с паттернами проектирования, их определением и классификацией. Обзор паттернов GoF. Паттерн Синглтон.
5.1. Теоретическая часть
Паттерны проектирования
В процессе разработки мы сталкиваемся часто с достаточно похожими проблемами, встречаемся с тяжело поддерживаемым кодом. И хотелось бы иметь какие-то общепринятые способы решения для стандартных проблем. И такими решениями являются паттерны проектирования. Следует уточнить несколько моментов:
1) паттерн проектирования не решение всех проблем. Он лишь позволяет помочь решить какие-то конкретные случаи;
2) можно создавать хороший поддерживаемый код и без паттернов проектирования. Они лишь подспорье к разработке;
3) стоит знать паттерны проектирования, так как они используются во многих фреймворках и библиотеках, они облегчают дальнейшее понимание той или иной технологии.
Паттернов огромное количество, но мы остановимся на важнейших – паттернах GoF.
Паттерны GoF
Паттерны GoF делятся на 3 вида:
1) порождающие;
2) структурные;
3) поведенческие.
Паттерн Синглтон (Singleton)
Синглтон – порождающий паттерн проектирования. Он позволяет гарантировать, что будет существовать ровно один объект существующего класса. Этот паттерн используется практически во всех возможных

приложениях, является невероятно полезным. В первую очередь, чтобы реализовать данный паттерн, нужно запретить возможность другому коду вызывать конструктор. Для этого требуется приватный конструктор.
Дальнейшая реализация различается у разных способов. Приведем пример двух способов:
1) через метод getInstance() с ленивой инициализацией: public class Singleton { private Singleton instance; public synchronized Singleton getInstance() { if(instance == null) { instance = new Singleton(); return instance;
} return instance;
}
}
2) через enum: public enum Singleton {
INSTANCE; public Singleton getInstance() { return INSTANCE;
}
}
5.2. Задание
Реализовать паттерн Singleton как минимум 3-мя способами.

6. ПРАКТИЧЕСКАЯ РАБОТА № 6
Цель работы
Знакомство с реализацией порождающих паттернов проектирования.
6.1. Теоретическая часть
Порождающие паттерны проектирования отвечают за удобное безопасное создание объектов или групп объектов.
Паттерн «Фабричный метод» – определяет интерфейс создания объектов, позволяя подклассам менять тип создаваемых объектов (рисунок 3).
Рисунок 3 – Паттерн «Фабричный метод»
Паттерн «Абстрактная фабрика» – позволяет создавать семейства определенных объектов (рисунок 4). Фактически является расширением паттерна «Фабричный метод».

Рисунок 4 – Паттерн «Абстрактная фабрика»
Паттерн «Строитель» – разделяет создание объекта на отдельные шаги, а также позволяет использовать один и тот же код создания для получения различных представлений (рисунок 5).
Рисунок 5 – Паттерн «Строитель»
Паттерн «Прототип» – позволяет копировать объекты без обращения к приватному состоянию извне (рисунок 6).

Рисунок 6 – Паттерн «Прототип»
6.2. Задание
Написать реализацию паттернов «Фабричный метод», «Абстрактная фабрика», «Строитель», «Прототип».

7. ПРАКТИЧЕСКАЯ РАБОТА № 7
Цель работы
Реализация структурных паттернов проектирования.
7.1. Теоретическая часть
Структурные паттерны проектирования играют не менее важную роль, нежели остальные паттерны. Они отвечают за построение удобной структуры и иерархии классов, которая делает код более поддерживаемым.
Рассмотрим основные структурные паттерны проектирования.
Паттерн «Адаптер» позволяет какой-то объект с одним интерфейсом подстроить под другой интерфейс (рисунок 7).
Рисунок 7 – Паттерн «Адаптер»
Паттерн «Мост» разделяет класс на две независимые части – абстракцию и реализацию (рисунок 8).


Рисунок 8 – Паттерн «Мост»
Паттерн «Компоновщик» позволяет сгруппировать множество объектов в древовидную структуру (рисунок 9).
Рисунок 9 – Паттерн «Компоновщик»
Паттерн «Декоратор» позволяет добавлять новую функциональность объекту, является некоторой оберткой над классом (рисунок 10). Не управляет жизненным циклом объекта.
Рисунок 10 – Паттерн «Декоратор»
Паттерн «Фасад» используется для предоставления простой абстракции над некоей сложной системой (рисунок 11).

Рисунок 11 – Паттерн «Фасад»
Паттерн «Легковес» используется для экономии памяти, разделяя общее состояние между множеством объектов (рисунок 12). Удобно использовать, когда есть очень много объектов с схожим состоянием.
Рисунок 12 – Паттерн «Легковес»
Паттерн «Заместитель» (Прокси) подставляет вместо объектов специальные объекты заместители, добавляя дополнительную логику вокруг вызовов методов (рисунок 13). Может управлять жизненным циклом объекта, который проксирует.

Рисунок 13 – Паттерн «Заместитель»
7.2. Задание
Написать реализацию паттерна в соответствии с вариантом индивидуального задания.
7.3. Варианты индивидуального задания
1) Адаптер, Мост.
2) Мост, Компоновщик.
3) Компоновщик, Декоратор.
4) Декоратор, Фасад.
5) Фасад, Легковес.
6) Легковес, Заместитель.
7) Заместитель, Адаптер.
8) Адаптер, Декоратор.
9) Декоратор, Легковес.
10) Легковес, Компоновщик.
11) Компоновщик, Фасад.
12) Фасад, Заместитель.
13) Заместитель, Компоновщик.
14) Компоновщик, Фасад.
15) Фасад, Адаптер.

8. ПРАКТИЧЕСКАЯ РАБОТА № 8
Цель работы
Реализация поведенческих паттернов проектирования.
8.1. Теоретическая часть
Поведенческие паттерны проектирования позволяют расширять поведение системы и взаимодействие различных объектов между собой.
Паттерн «Цепочка обязанностей» позволяет передавать запросы по специальной цепочке обработчиков (рисунок 14).
Рисунок 14 – Паттерн «Цепочка обязанностей»
Паттерн «Команда» инкапсулирует некий запрос в объект, позволяя передавать их другим объектам для обработки (рисунок 15).
Рисунок 15 – Паттерн «Команда»


Паттерн «Итератор» позволяет обходить множества элементов последовательно (рисунок 16).
Рисунок 16 – Паттерн «Итератор»
Паттерн «Посредник» перемещает взаимодействие между отдельными объектами в специальный класс-посредник (рисунок 17).
Рисунок 17 – Паттерн «Посредник»
Паттерн «Снимок» позволяет сохранять предыдущие состояние некоторого объекта, не раскрывая его реализации (рисунок 18).

Рисунок 18 – Паттерн «Снимок»
Паттерн «Наблюдатель» используется для создания механизма подписки на события (рисунок 19).
Рисунок 19 – Паттерн «Наблюдатель»
Паттерн «Состояние» позволяет объектам менять свое поведение в зависимости от состояния (рисунок 20).

Рисунок 20 – Паттерн «Состояние»
Паттерн «Стратегия» позволяет определить семейство различных алгоритмов, которые можно заменять (рисунок 21).
Рисунок 21– Паттерн «Стратегия»
Определяет некоторый алгоритм и позволяет его отдельные шаги делегировать подклассам (рисунок 22).

Рисунок 22 – Паттерн «Стратегия»
Паттерн «Посетитель» позволяет выполнять одну операцию над группой различных объектов, при этом позволяя создавать новую операцию без изменения классов, над которыми она выполняется (рисунок 23).
Рисунок 23 – Паттерн «Посетитель»
8.2. Задание
Написать реализацию паттерна в соответствии с вариантом индивидуального задания.
8.3. Варианты индивидуального задания
1) Цепочка обязанностей, Команда.
2) Команда, Итератор.

3) Итератор, Посредник.
4) Посредник, Снимок.
5) Снимок, Наблюдатель.
6) Наблюдатель, Состояние.
7) Состояние, Стратегия.
8) Стратегия, Шаблонный метод.
9) Шаблонный метод, Посетитель.
10) Посетитель, Команда.
11) Команда, Стратегия.
12) Посредник, Итератор.
13) Состояние, Цепочка обязанностей.
14) Шаблонный метод, Посетитель.
15) Посетитель, Посредник.

1   2   3   4   5

9. ПРАКТИЧЕСКАЯ РАБОТА № 9
Цель работы
Знакомство с системой сборки приложения. Gradle.
9.1. Теоретическая часть
Разработка – сложный процесс, и все монотонные процессы так или иначе автоматизируются для того, чтобы программист думал о бизнес-логике, а не об инфраструктуре приложения. Сборка приложения, работа с зависимостями также автоматизирована, и для этого используются системы сборки приложений. Основные функции данных систем:
1) организация механизма сборки приложения из исходного кода;
2) управление зависимостями;
3) предоставление механизмов для настройки алгоритма сборки приложения.
Для Java наиболее известными системами сборки приложений являются
Maven и Gradle.
Maven
Maven основан на использовании xml файла, в котором описывается вся нужная для сборщика приложения информация: зависимости, плагины для изменения сборки, версия самого приложения и версия Java, дополнительная информация.
Gradle
Gradle основан на groovy файле build.gradle, в котором также описывается основная информация. На рисунке 24 приведен пример build.gradle.

Рисунок 24 – Пример build.gradle
Рассмотрим основные части данного файла (рисунки 25-32).
Рисунок 25 – Пример build.gradle, часть 1

В plugins описаны все плагины – специальные дополнения, которые отвечают как за управление зависимостями, так и изменяют алгоритм сборки приложения, а также добавляют различные Gradle Tasks. Что такое Gradle
Tasks будет пояснено далее.
Рисунок 26 – Пример build.gradle, часть 2
Далее описываются различные конфигурации: название группы пакетов, версия приложения, версия Java, дополнительные конфигурации.
Рисунок 27 – Пример build.gradle, часть 3
В repositories описываются репозитории – хранилища, откуда будут загружаться зависимости.
Рисунок 28 – Пример build.gradle, часть 4

Далее описываются непосредственно сами зависимости. Есть много типов видимости для зависимостей, вот лишь самые основные:
– implementation – зависимость на этапе компиляции, также предоставляется как библиотека для использования на этапе runtime;
– compileOnly – зависимость только на этапе компиляции;
– runtimeOnly – зависимость только на этапе runtime;
– testImplementation – implementation для запуска тестов;
– annotationProcessor – использование процессора аннотаций.
Часто требуется как-то кастомизировать процесс сборки приложения.
Для этого в Gradle используются задачи Gradle Tasks. По сути, Gradle task – просто groovy script, который запускается, когда ты его вызываешь. Но удобство в том, что можно строить любые цепочки задач для сборки приложений, а также использовать задачи из плагинов или стандартные задачи Gradle.
Рисунок 29 – Пример build.gradle, часть 5
Ниже приведен вывод при запуске данной задачи.
Рисунок 30 – Пример build.gradle, часть 6
Далее приведен пример простой цепочки из задач.