Ответ
Паттерн Proxy (Заместитель) предоставляет объект-субститут, который контролирует доступ к реальному объекту. Клиент взаимодействует с прокси, который делегирует вызовы целевому объекту, добавляя при необходимости свою логику.
Ключевой механизм: Прокси реализует тот же интерфейс, что и оригинальный объект, что позволяет ему быть его полной заменой.
Пример: Динамический прокси в Java (логирование вызовов)
import java.lang.reflect.*;
// 1. Общий интерфейс
interface DatabaseService {
String fetchData(String query);
}
// 2. Реальный объект
class RealDatabaseService implements DatabaseService {
public String fetchData(String query) {
return "Result for: " + query;
}
}
// 3. Создание прокси с обработчиком вызовов
InvocationHandler loggingHandler = new InvocationHandler() {
private final RealDatabaseService realService = new RealDatabaseService();
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("[LOG] Calling method: " + method.getName());
// Дополнительная логика: проверка прав, кеширование, замер времени
Object result = method.invoke(realService, args); // Делегирование вызова
System.out.println("[LOG] Method finished.");
return result;
}
};
// 4. Создание экземпляра прокси
DatabaseService proxyInstance = (DatabaseService) Proxy.newProxyInstance(
DatabaseService.class.getClassLoader(),
new Class[]{DatabaseService.class}, // Интерфейс, который реализует прокси
loggingHandler
);
// Клиентский код работает с прокси
String data = proxyInstance.fetchData("SELECT * FROM users");
// Вывод: [LOG] Calling method: fetchData
// [LOG] Method finished.
Типы прокси в Java:
- Динамические прокси (как в примере): Создаются во время выполнения для интерфейсов.
- Прокси на основе наследования (CGLIB): Создают подкласс для классов (не только интерфейсов).
- Виртуальные прокси: Ленивая инициализация тяжёлого объекта.
- Защищающие прокси (Protection Proxy): Контроль прав доступа.