Ответ
Прокси (Proxy) — это структурный паттерн, который предоставляет объект-заместитель или placeholder для другого объекта, контролируя доступ к нему. Прокси и реальный объект имеют одинаковый интерфейс, что позволяет клиенту работать с прокси так, как будто это реальный объект.
Зачем он нужен? Чтобы добавить дополнительный уровень косвенности для управления доступом, кэширования, логгирования, отложенной инициализации или защиты реального объекта.
Основные типы прокси:
- Виртуальный прокси (Lazy Initialization): Создает дорогой объект только по требованию.
- Защищающий прокси (Protection Proxy): Контролирует доступ к объекту на основе прав.
- Прокси удаленного доступа (Remote Proxy): Представляет объект, находящийся в другом адресном пространстве.
- Прокси для логирования/кэширования: Добавляет сквозную функциональность.
Пример на Java (Виртуальный прокси для тяжелого изображения):
// 1. Общий интерфейс
interface Image {
void display();
}
// 2. Реальный объект (дорогой в создании)
class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk(); // Долгая операция
}
private void loadFromDisk() {
System.out.println("Loading image: " + filename);
}
@Override
public void display() {
System.out.println("Displaying image: " + filename);
}
}
// 3. Прокси-заместитель
class ProxyImage implements Image {
private RealImage realImage; // Ссылка на реальный объект
private String filename;
public ProxyImage(String filename) {
this.filename = filename;
}
@Override
public void display() {
// Ленивая загрузка: создаем реальный объект только при первом вызове
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
// 4. Использование
public class Main {
public static void main(String[] args) {
Image image = new ProxyImage("high_res_photo.jpg");
// RealImage еще НЕ создан
System.out.println("Image object created. RealImage not loaded yet.");
image.display(); // Первый вызов загружает и показывает
// Loading image: high_res_photo.jpg
// Displaying image: high_res_photo.jpg
image.display(); // Второй вызов использует уже загруженный объект
// Displaying image: high_res_photo.jpg
}
}
Ключевые преимущества:
- Контролируемый доступ. Можно добавить проверки до вызова реального объекта.
- Ленивая инициализация. Откладывает создание ресурсоемких объектов.
- Дополнительная логика. Легко добавить кэширование, логирование, безопасность.
- Прозрачность для клиента. Клиентский код работает с интерфейсом, не зная о прокси.
Реализация в Java: Механизм динамических прокси (java.lang.reflect.Proxy) часто используется в AOP (Aspect-Oriented Programming) и фреймворках вроде Spring.