Где используется декоратор в Java Core?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Паттерн Decorator (Декоратор) в Java Core
Определение
Decorator Pattern — это структурный паттерн, позволяющий динамически добавлять новые функции к объектам, оборачивая их в объекты-декораторы. При этом не изменяется исходный класс.
Где используется в Java Core
1. I/O Streams - Самый очевидный пример
В пакете java.io декоратор используется повсеместно для расширения функциональности потоков.
// Базовый поток ввода
InputStream input = new FileInputStream("file.txt");
// Декоратор 1: буферизация (добавляет скорость)
BufferedInputStream buffered = new BufferedInputStream(input);
// Декоратор 2: преобразование данных (добавляет декодирование)
InputStreamReader reader = new InputStreamReader(buffered, StandardCharsets.UTF_8);
// Декоратор 3: построчное чтение (добавляет удобство)
BufferedReader lineReader = new BufferedReader(reader);
// Использование
String line;
while ((line = lineReader.readLine()) != null) {
System.out.println(line);
}
Иерархия: FileInputStream -> BufferedInputStream -> InputStreamReader -> BufferedReader
2. OutputStream - Отправка данных
// Базовый поток вывода
OutputStream output = new FileOutputStream("file.txt");
// Декоратор 1: буферизация
BufferedOutputStream buffered = new BufferedOutputStream(output);
// Декоратор 2: сжатие данных
GZIPOutputStream compressed = new GZIPOutputStream(buffered);
// Использование
compressed.write("Compressed data".getBytes());
compressed.close(); // Закрывает всю цепь
3. Collections - Обёртывание коллекций
Методы Collections возвращают декораторы, которые добавляют функциональность.
// Исходный список
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
// Декоратор 1: неизменяемость (добавляет защиту от изменений)
List<String> unmodifiable = Collections.unmodifiableList(names);
// unmodifiable.add("Charlie"); // Выбросит исключение
// Декоратор 2: синхронизация (добавляет потокобезопасность)
List<String> synchronized = Collections.synchronizedList(new ArrayList<>(names));
// Декоратор 3: несколько уровней
Set<String> syncSet = Collections.synchronizedSet(new HashSet<>(names));
4. FilterInputStream и FilterOutputStream - Абстрактные декораторы
Эти классы служат базой для создания пользовательских декораторов.
// FilterInputStream - абстрактная основа для читающих декораторов
public class UppercaseInputStream extends FilterInputStream {
public UppercaseInputStream(InputStream in) {
super(in);
}
@Override
public int read() throws IOException {
int c = super.read();
return (c == -1) ? c : Character.toUpperCase(c);
}
}
// Использование
try (InputStream input = new FileInputStream("input.txt");
InputStream uppercase = new UppercaseInputStream(input);
InputStreamReader reader = new InputStreamReader(uppercase)) {
int c;
while ((c = reader.read()) != -1) {
System.out.print((char) c); // Будет выводить в UPPERCASE
}
}
5. DataInputStream и DataOutputStream - Типизированные данные
// Запись типизированных данных
try (OutputStream output = new FileOutputStream("data.bin");
DataOutputStream dos = new DataOutputStream(output)) {
dos.writeInt(100); // Запись целого числа
dos.writeDouble(3.14); // Запись вещественного числа
dos.writeUTF("Hello"); // Запись строки
}
// Чтение типизированных данных
try (InputStream input = new FileInputStream("data.bin");
DataInputStream dis = new DataInputStream(input)) {
int num = dis.readInt(); // Чтение целого числа
double pi = dis.readDouble(); // Чтение вещественного числа
String text = dis.readUTF(); // Чтение строки
System.out.println(num + ", " + pi + ", " + text);
}
6. PrintStream и PrintWriter - Удобная печать
// PrintStream - это декоратор FilterOutputStream
public static void main(String[] args) {
// System.out - это PrintStream (декоратор OutputStream)
PrintStream out = System.out;
out.println("Hello"); // println добавляет удобство
// PrintWriter - для символьных потоков
try (PrintWriter writer = new PrintWriter(new FileWriter("output.txt"))) {
writer.println("Line 1");
writer.printf("Number: %d\n", 42);
writer.format("Double: %.2f%n", 3.14159);
} catch (IOException e) {
e.printStackTrace();
}
}
7. Scanner - Удобное считывание
// Scanner - это декоратор, обёртывающий InputStream
try (Scanner scanner = new Scanner(new FileInputStream("data.txt"))) {
// Декоратор добавляет удобные методы для чтения
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(line);
}
// Типизированное чтение
scanner.reset();
while (scanner.hasNextInt()) {
int num = scanner.nextInt();
System.out.println(num);
}
}
8. Compression - Сжатие потоков
import java.util.zip.*;
// ZIPInputStream - декоратор для распаковки
try (FileInputStream fis = new FileInputStream("archive.zip");
ZipInputStream zis = new ZipInputStream(fis)) {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
System.out.println("File: " + entry.getName());
// Читаем содержимое файла
}
}
// ZIPOutputStream - декоратор для упаковки
try (FileOutputStream fos = new FileOutputStream("archive.zip");
ZipOutputStream zos = new ZipOutputStream(fos)) {
// Добавляем файл в архив
ZipEntry entry = new ZipEntry("file.txt");
zos.putNextEntry(entry);
zos.write("Content".getBytes());
zos.closeEntry();
}
Архитектурная схема IO Decorators
┌─────────────────────────────────────────────────────────┐
│ BufferedReader (удобство - readLine) │
├─────────────────────────────────────────────────────────┤
│ InputStreamReader (преобразование - декодирование) │
├─────────────────────────────────────────────────────────┤
│ BufferedInputStream (производительность - буферизация) │
├─────────────────────────────────────────────────────────┤
│ FileInputStream (базовый поток) │
└─────────────────────────────────────────────────────────┘
Практический пример: чтение различных типов файлов
public class FileProcessor {
// Чтение текстового файла
public static void readTextFile(String path) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream(path),
StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
}
// Чтение сжатого файла
public static void readCompressedFile(String path) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(
new GZIPInputStream(
new FileInputStream(path))))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
}
// Запись с форматированием
public static void writeFormattedFile(String path) throws IOException {
try (PrintWriter writer = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(path),
StandardCharsets.UTF_8)))) {
writer.println("Line 1");
writer.printf("Number: %d%n", 42);
writer.format("Array: %s%n", new int[]{1, 2, 3});
}
}
}
Правило использования Decorators
// ПРАВИЛО: каждый уровень добавляет одну ответственность
// 1 уровень: базовый источник
InputStream input = new FileInputStream("file.txt");
// 2 уровень: производительность (буферизация)
input = new BufferedInputStream(input);
// 3 уровень: преобразование (декодирование)
InputStreamReader reader = new InputStreamReader(input, StandardCharsets.UTF_8);
// 4 уровень: удобство (построчное чтение)
BufferedReader lineReader = new BufferedReader(reader);
Преимущества Decorator в Java Core
- Гибкость — можно комбинировать декораторы в любом порядке
- Разделение ответственности — каждый класс отвечает за одну функцию
- Расширяемость — легко добавлять новые декораторы
- Переиспользование — один декоратор работает с любым потоком
- Производительность — можно добавить буферизацию
- Типизация — можно добавить типизированное чтение/запись
Резюме
Декоратор — это один из самых часто используемых паттернов в Java Core. Он активно применяется в пакете java.io для создания гибкой системы работы с потоками, позволяя комбинировать различные функциональности (буферизация, компрессия, декодирование, форматирование) в единую цепь обработки данных. Понимание этого паттерна критически важно для эффективной работы с файлами и сетевыми соединениями в Java.