← Назад к вопросам

Где используется декоратор в Java Core?

2.0 Middle🔥 121 комментариев
#SOLID и паттерны проектирования

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Паттерн 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

  1. Гибкость — можно комбинировать декораторы в любом порядке
  2. Разделение ответственности — каждый класс отвечает за одну функцию
  3. Расширяемость — легко добавлять новые декораторы
  4. Переиспользование — один декоратор работает с любым потоком
  5. Производительность — можно добавить буферизацию
  6. Типизация — можно добавить типизированное чтение/запись

Резюме

Декоратор — это один из самых часто используемых паттернов в Java Core. Он активно применяется в пакете java.io для создания гибкой системы работы с потоками, позволяя комбинировать различные функциональности (буферизация, компрессия, декодирование, форматирование) в единую цепь обработки данных. Понимание этого паттерна критически важно для эффективной работы с файлами и сетевыми соединениями в Java.

Где используется декоратор в Java Core? | PrepBro