Что такое паттерн Proxy и каковы его основные типы?

«Что такое паттерн Proxy и каковы его основные типы?» — вопрос из категории Паттерны, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Паттерн Proxy (Заместитель) — это структурный паттерн проектирования, который предоставляет объект-заменитель или placeholder для другого объекта. Прокси контролирует доступ к оригинальному объекту, позволяя выполнить дополнительную логику до или после основного вызова.

Классическая структура:

  1. Subject (Интерфейс): Общий интерфейс для RealSubject и Proxy.
  2. RealSubject (Реальный объект): Основной объект, содержащий бизнес-логику.
  3. Proxy (Заместитель): Объект, хранящий ссылку на RealSubject, управляет доступом к нему.

Пример: Virtual Proxy для ленивой загрузки изображения

// Subject
interface Image {
    void display();
}

// RealSubject
class RealImage implements Image {
    private String fileName;
    public RealImage(String fileName) {
        this.fileName = fileName;
        loadFromDisk(); // Ресурсоемкая операция
    }
    private void loadFromDisk() { System.out.println("Loading: " + fileName); }
    public void display() { System.out.println("Displaying: " + fileName); }
}

// Proxy
class ProxyImage implements Image {
    private RealImage realImage;
    private String fileName;
    public ProxyImage(String fileName) { this.fileName = fileName; }
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(fileName); // Создание отложено до первого вызова
        }
        realImage.display();
    }
}

// Клиентский код
Image image = new ProxyImage("photo.jpg");
image.display(); // Вывод: "Loading: photo.jpg" -> "Displaying: photo.jpg"
image.display(); // Вывод: "Displaying: photo.jpg" (объект уже загружен)

Основные типы прокси:

  • Виртуальный прокси (Virtual Proxy): Откладывает создание ресурсоемкого объекта до момента его реального использования (ленивая загрузка).
  • Защищающий прокси (Protection Proxy): Контролирует доступ к объекту на основе прав вызывающего кода.
  • Удаленный прокси (Remote Proxy): Представляет локальную заглушку для объекта, находящегося в другом адресном пространстве (например, RMI, gRPC).
  • Кэширующий прокси (Caching Proxy): Сохраняет результаты запросов и возвращает кэшированные данные для повторных вызовов.
  • Логирующий прокси (Logging Proxy): Регистрирует вызовы методов и их параметры.

В Java прокси часто создаются динамически с помощью java.lang.reflect.Proxy или библиотек (например, Spring AOP).