Паттерн "Заместитель" (Proxy) в Java — доступ, кэш и lazy loading
Обзор — в структурных паттернах. Здесь — Proxy на Java: объект с тем же интерфейсом, что и "настоящий" сервис, но с перехватом до/после вызова.
Задача паттерна
Proxy подменяет реальный объект суррогатом с тем же контрактом. Клиент вызывает прокси; прокси может проверить права, закэшировать ответ или отложить создание тяжёлого объекта.
Пример — документы с доступом и кэшем
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
interface DocumentService {
String loadDocument(String docId);
}
class RealDocumentService implements DocumentService {
@Override
public String loadDocument(String docId) {
System.out.println("Загрузка из хранилища: " + docId);
return "Содержимое документа " + docId;
}
}
final class SecurityContext {
private static final ThreadLocal<String> currentRole = new ThreadLocal<>();
static void setCurrentRole(String role) {
currentRole.set(role);
}
static String getCurrentRole() {
return currentRole.get();
}
}
class DocumentServiceProxy implements DocumentService {
private final RealDocumentService realService = new RealDocumentService();
private final Map<String, String> cache = new HashMap<>();
private final Set<String> allowedRoles;
DocumentServiceProxy(Set<String> allowedRoles) {
this.allowedRoles = allowedRoles;
}
@Override
public String loadDocument(String docId) {
String role = SecurityContext.getCurrentRole();
if (!allowedRoles.contains(role)) {
throw new SecurityException("Нет доступа");
}
return cache.computeIfAbsent(docId, realService::loadDocument);
}
}
SecurityContext.setCurrentRole("ADMIN");
DocumentService service = new DocumentServiceProxy(Set.of("ADMIN", "EDITOR"));
String doc = service.loadDocument("report-2026");
Виды прокси в Java
| Тип | Пример |
|---|---|
| Protection | Проверка роли перед вызовом (Spring Security) |
| Caching | computeIfAbsent в примере выше |
| Lazy | Hibernate lazy-прокси сущности (JPA) |
| Remote | RMI, gRPC-клиент как удалённый суррогат |
| Logging / metrics | Spring AOP @Around |
JDK динамические прокси (java.lang.reflect.Proxy) и ByteBuddy/CGLIB в Spring создают прокси во время выполнения без ручного класса-обёртки.
Proxy и Decorator
| Proxy | Decorator | |
|---|---|---|
| Фокус | Контроль доступа и жизненного цикла | Добавление поведения |
| Клиент | Может не знать о существовании real subject | Ожидает цепочку обёрток |
| Пример | Lazy load, security | new BufferedInputStream(new FileInputStream(...)) |
Когда применять и риски
Прокси уместен, когда нужен прозрачный контроль без изменения клиентского кода.
Несколько слоёв прокси (AOP + security + cache) усложняют отладку и добавляют задержку — логируйте цепочку перехватчиков в dev-среде.
См. также
См. также
Другие статьи этого же раздела в боковом меню (как на странице "О разделе"). Паттерн — это повторяющийся шаблон, узор или схема. Паттерны встречаются повсюду — в природе, архитектуре, поведении людей и, конечно, в программировании. Порождающие паттерны проектирования — это группа шаблонов, направленных на решение задач, связанных с созданием объектов. Структурные паттерны — это группа шаблонов проектирования, решающих задачи организации классов и объектов таким образом, чтобы обеспечить гибкую архитектуру программного обеспечения. Поведенческие паттерны — это группа шаблонов проектирования, которые определяют способы взаимодействия объектов и распределения ответственности между ними. Архитектурные паттерны — это проверенные решения для организации структуры программного обеспечения. Интеграция систем — одна из центральных задач в современной разработке программного обеспечения. Паттерны доменного моделирования представляют собой проверенные решения для организации бизнес-логики в программных системах. Паттерн Strategy в C# — классическая реализация через интерфейс, замена на Func и Action, DI и критерии выбора без лишних абстракций. Паттерн Iterator в C# — ручной IEnumerator, генерация итератора компилятором через yield return, ленивость, LINQ и случаи, когда класс писать всё же нужно. Abstract Factory в C# и .NET — классическая схема через интерфейсы, замена через DI-контейнер, фабричный делегат и keyed services в .NET 8. Паттерн Command в C# — классическая схема, делегаты, MediatR, очередь задач, undo и критерии выбора между объектом команды и простым вызовом сервиса. Паттерн Observer в C# — event и делегаты, IObservable IObserver, слабая связанность, отписка и как не поймать утечки памяти в долгоживущих сервисах.Обзор паттернов проектирования
Порождающие паттерны
Структурные паттерны
Поведенческие паттерны
Архитектурные паттерны
Паттерны интеграции внешних систем
Паттерны проектирования доменных моделей
Стратегия в C#
Итератор в C#
Фабрика в C#
Команда в C#
Наблюдатель в C#