Что такое паттерн Прокси и приведи пример его использования?

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

Ответ

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

Пример: Ленивая загрузка (Lazy Loading) тяжелого объекта.

// 1. Общий интерфейс для реального объекта и прокси
interface ExpensiveService {
    void process();
}

// 2. Реальный объект с "тяжелой" инициализацией
class ExpensiveServiceImpl implements ExpensiveService {
    public ExpensiveServiceImpl() {
        // Долгая операция: загрузка из БД, чтение файла и т.д.
        System.out.println("Creating real ExpensiveService...");
    }
    @Override
    public void process() {
        System.out.println("Processing by real service.");
    }
}

// 3. Прокси-заместитель, откладывающий создание реального объекта
class ExpensiveServiceProxy implements ExpensiveService {
    private ExpensiveService realService; // Ссылка на реальный объект

    @Override
    public void process() {
        // Ленивая инициализация: создаем объект только при первом вызове
        if (realService == null) {
            realService = new ExpensiveServiceImpl();
        }
        // Делегируем вызов реальному объекту
        realService.process();
    }
}

// 4. Использование клиентом
public class Client {
    public static void main(String[] args) {
        // Реальный объект еще не создан
        ExpensiveService proxy = new ExpensiveServiceProxy();
        System.out.println("Proxy created.");
        // Реальный объект создается только здесь, при первом вызове
        proxy.process();
    }
}

Другие типы прокси и их применение:

  • Виртуальный прокси (как в примере): Для ленивой загрузки ресурсов.
  • Защищающий прокси (Protection Proxy): Для контроля прав доступа к объекту.
  • Удаленный прокси (Remote Proxy): Для представления объекта, находящегося в другом адресном пространстве (например, RPC, REST-клиент).
  • Прокси для логирования/кэширования: Добавляет сквозную функциональность.

Почему это полезно: Улучшает производительность и безопасность, разделяя ответственности.