В мире разработки обертки (wrappers) — это мощный инструмент, который позволяет инкапсулировать сложную логику, добавлять новую функциональность или адаптировать существующие классы для более удобного использования. В этой статье мы рассмотрим, что такое обертки, какие задачи они решают, и как их правильно создавать на Java. Мы также приведем примеры реального применения, чтобы показать их пользу.
Что такое обертка (wrapper)?
Обертка — это класс, который «оборачивает» другой объект или функциональность, предоставляя новый интерфейс, изменяя поведение или добавляя дополнительные функции. Обертки часто используют для следующих целей:
-
Инкапсуляция логики. Упрощение взаимодействия с более сложными системами.
-
Добавление новой функциональности. Расширение поведения объекта без изменения исходного кода.
-
Повышение удобства использования. Создание более понятного или лаконичного интерфейса.
-
Интеграция. Адаптация сторонних библиотек или API под нужды проекта.
Примеры оберток в стандартной библиотеке Java
Java предоставляет множество встроенных оберток. Например:
-
Классы
Integer
,Double
,Boolean
— это обертки для примитивных типов данных. -
BufferedReader
иBufferedWriter
— обертки для работы с потоками, добавляющие буферизацию.
Давайте создадим свои обертки и разберем, как их использовать.
Типы оберток и их применение
1. Обертки для примитивных типов
Предположим, нам нужно работать с числовыми значениями, добавляя к ним дополнительную проверку. Создадим класс PositiveInteger
, который гарантирует, что число всегда будет положительным.
public class PositiveInteger { private final int value; public PositiveInteger(int value) { if (value <= 0) { throw new IllegalArgumentException("Value must be positive!"); } this.value = value; } public int getValue() { return value; } public PositiveInteger add(int number) { return new PositiveInteger(this.value + number); } @Override public String toString() { return "PositiveInteger{" + "value=" + value + '}'; } }
Использование:
public class Main { public static void main(String[] args) { PositiveInteger number = new PositiveInteger(10); System.out.println(number); // PositiveInteger{value=10} PositiveInteger newNumber = number.add(5); System.out.println(newNumber); // PositiveInteger{value=15} // PositiveInteger invalid = new PositiveInteger(-5); // Ошибка IllegalArgumentException } }
Преимущества:
-
Обеспечение неизменности значения (
final
). -
Валидация на этапе создания объекта.
2. Обертки для сторонних библиотек
Сторонние библиотеки могут предоставлять неудобные или слишком сложные интерфейсы. Например, представим, что мы работаем с Connection
для базы данных и хотим добавить автоматическое закрытие соединения.
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class ConnectionWrapper { private Connection connection; public ConnectionWrapper(String url, String user, String password) throws SQLException { this.connection = DriverManager.getConnection(url, user, password); } public void executeQuery(String query) throws SQLException { try (var statement = connection.createStatement()) { var resultSet = statement.executeQuery(query); while (resultSet.next()) { System.out.println(resultSet.getString(1)); } } } public void close() throws SQLException { if (connection != null) { connection.close(); } } }
Использование:
public class Main { public static void main(String[] args) { try (ConnectionWrapper db = new ConnectionWrapper("jdbc:h2:mem:test", "user", "password")) { db.executeQuery("SELECT 1"); } catch (SQLException e) { e.printStackTrace(); } } }
Преимущества:
-
Автоматизация рутинных задач (закрытие ресурсов).
-
Улучшение читаемости кода.
3. Обертки для добавления функциональности
Часто требуется добавить к объекту логирование или мониторинг. Например, обернем List
, чтобы фиксировать добавленные элементы.
import java.util.ArrayList; import java.util.List; public class LoggingList<T> { private final List<T> list = new ArrayList<>(); public void add(T element) { System.out.println("Adding element: " + element); list.add(element); } public T get(int index) { System.out.println("Getting element at index: " + index); return list.get(index); } public int size() { return list.size(); } }
Использование:
public class Main { public static void main(String[] args) { LoggingList<String> loggingList = new LoggingList<>(); loggingList.add("Hello"); loggingList.add("World"); System.out.println(loggingList.get(0)); // Hello } }
Преимущества:
-
Логирование операций.
-
Минимальное изменение исходного кода.
4. Обертки для асинхронных задач
Обертки полезны для управления асинхронным кодом, особенно с CompletableFuture
. Создадим обертку, упрощающую обработку задач.
import java.util.concurrent.CompletableFuture; public class AsyncTask { private final CompletableFuture<Void> task; public AsyncTask(Runnable action) { this.task = CompletableFuture.runAsync(action); } public void onComplete(Runnable callback) { task.thenRun(callback); } public void onError(Runnable errorCallback) { task.exceptionally(ex -> { errorCallback.run(); return null; }); } }
Использование:
public class Main { public static void main(String[] args) { AsyncTask task = new AsyncTask(() -> { System.out.println("Task is running..."); if (Math.random() > 0.5) throw new RuntimeException("Error occurred!"); }); task.onComplete(() -> System.out.println("Task completed successfully.")); task.onError(() -> System.out.println("Task failed.")); } }
Преимущества:
-
Простое управление асинхронными операциями.
-
Уменьшение шаблонного кода.
Когда использовать обертки?
Использование оберток оправдано в следующих случаях:
-
Когда исходный интерфейс слишком сложный.
-
Когда требуется добавить новую функциональность без изменения оригинального кода.
-
Для соблюдения принципа единственной ответственности (SRP).
-
Для повышения читаемости и модульности кода.
Обертки в Java — это универсальный инструмент, который помогает разработчикам улучшать качество и удобство работы с кодом. Они могут быть использованы в самых разных сценариях: от простой валидации данных до интеграции с внешними системами. Если правильно их применять, обертки значительно упрощают разработку и делают ваш код более поддерживаемым.
ссылка на оригинал статьи https://habr.com/ru/articles/868786/
Добавить комментарий