Ответ
Паттерн Proxy (Заместитель) предоставляет суррогатный объект, контролирующий доступ к другому объекту. Основные типы: удаленный, виртуальный, защищающий, логирующий.
Пример защищающего прокси (Protection Proxy):
-
Общий интерфейс:
public interface DatabaseAccess { void query(String sql) throws AccessDeniedException; } -
Реальный объект:
public class RealDatabaseAccess implements DatabaseAccess { @Override public void query(String sql) { System.out.println("Executing query: " + sql); // Реальная логика выполнения запроса к БД } } -
Прокси-объект (добавляет контроль доступа):
public class DatabaseAccessProxy implements DatabaseAccess { private RealDatabaseAccess realService; private String userRole; public DatabaseAccessProxy(String userRole) { this.userRole = userRole; } @Override public void query(String sql) throws AccessDeniedException { // Дополнительная логика ПЕРЕД вызовом реального объекта if (!"ADMIN".equals(userRole)) { throw new AccessDeniedException("User '" + userRole + "' cannot execute queries."); } // Ленивая инициализация реального объекта if (realService == null) { realService = new RealDatabaseAccess(); } // Делегирование вызова реальному объекту realService.query(sql); // Здесь можно добавить логику ПОСЛЕ вызова (логирование, кэширование) System.out.println("Query executed by: " + userRole); } } -
Использование клиентом:
public class Client { public static void main(String[] args) { DatabaseAccess adminAccess = new DatabaseAccessProxy("ADMIN"); try { adminAccess.query("DELETE FROM users"); // Успешно } catch (AccessDeniedException e) { e.printStackTrace(); } DatabaseAccess userAccess = new DatabaseAccessProxy("USER"); try { userAccess.query("SELECT * FROM users"); // Выбросит AccessDeniedException } catch (AccessDeniedException e) { System.out.println("Expected error: " + e.getMessage()); } } }
Преимущества:
- Контроль доступа: Прокси проверяет права перед выполнением операции.
- Ленивая инициализация (Виртуальный прокси): Ресурсоемкий объект создается только при необходимости.
- Дополнительная функциональность: Легко добавить логирование, кэширование, управление соединениями без изменения реального объекта.
Ответ 18+ 🔞
А, паттерн Proxy, блядь! Это ж как будто ты нанимаешь себе секретаря-хулигана, который стоит перед дверью и решает, кого пускать к тебе, а кому дать пизды. Заместитель, сука, в натуре!
Смотри, в чём прикол. Есть у тебя какой-то важный объект — база данных, тяжёлый сервис, файловая система, ёпта. И ты не хочешь, чтобы к нему лезли все подряд, как в публичный сортир. Вот тут и появляется этот самый прокси — такой здоровый буфер между клиентом и реальной штукой.
Основные разновидности, блядь:
- Удалённый (Remote): Когда реальный объект сидит на другом сервере, а прокси притворяется, что он тут, рядом, и просто пересылает запросы туда-сюда. Как курьер, блядь.
- Виртуальный (Virtual): Ленивая жопа! Не создаёт тяжёлый объект, пока реально не понадобится. «А, тебе картинку? Ща, бля, только загружу... ой, а она весит овердохуища гигабайт».
- Защищающий (Protection): Вот это наш случай, блядь! Стоит как вышибала в клубе и проверяет паспорт: «Ты кто такой? Админ? Проходи. Юзер? Иди нахуй, отсоси у тракториста».
- Логирующий (Logging): Стоит и всё записывает в блокнотик: «Вася в 12:05 пытался удалить всю базу, пидарас шерстяной».
Вот тебе пример, как этот защищающий вышибала работает:
-
Договоримся на берегу (интерфейс). Все должны знать, как с этой штукой разговаривать.
public interface DatabaseAccess { void query(String sql) throws AccessDeniedException; } -
Настоящий крутой чувак (реальный объект). Он просто делает свою работу.
public class RealDatabaseAccess implements DatabaseAccess { @Override public void query(String sql) { System.out.println("Executing query: " + sql); // Тут реально пошла жара, запрос летит в базу, сервера горят } } -
А вот и наш вышибала-прокси! Он решает, звать ли крутого чувака.
public class DatabaseAccessProxy implements DatabaseAccess { private RealDatabaseAccess realService; // Ссылка на того самого крутого чувака private String userRole; // А это роль того, кто стучится public DatabaseAccessProxy(String userRole) { this.userRole = userRole; } @Override public void query(String sql) throws AccessDeniedException { // ПРОВЕРКА ДОСТУПА, БЛЯДЬ! Всё начинается здесь. if (!"ADMIN".equals(userRole)) { // Если не админ — получай в табло и вали отсюда! throw new AccessDeniedException("User '" + userRole + "' cannot execute queries."); } // Ленивая инициализация: реального чувака будем беспокоить только если прошли проверку if (realService == null) { realService = new RealDatabaseAccess(); // «Эй, босс, проснись, работа есть!» } // Если добрались сюда — делегируем запрос настоящему объекту realService.query(sql); // Можно ещё что-то сделать после, например, залогировать System.out.println("Query executed by: " + userRole); } } -
Клиенты пытаются прорваться:
public class Client { public static void main(String[] args) { // Приходит админ — вышибала уважительно кивает DatabaseAccess adminAccess = new DatabaseAccessProxy("ADMIN"); try { adminAccess.query("DELETE FROM users"); // Успешно проходит } catch (AccessDeniedException e) { e.printStackTrace(); } // Приходит юзер — получает по ебалу DatabaseAccess userAccess = new DatabaseAccessProxy("USER"); try { userAccess.query("SELECT * FROM users"); // AccessDeniedException, в рот меня чих-пых! } catch (AccessDeniedException e) { System.out.println("Expected error: " + e.getMessage()); // «Так и знал, что не пустят» } } }
И в чём же, блядь, кайф?
- Контроль доступа: Прокси решает, кто достоин, а кто — манда с ушами. Безопасность, ёпта!
- Ленивая инициализация: Не грузим память и процессор, пока реально не надо. Экономия, блядь!
- Дополнительная функциональность: Хочешь логировать, кэшировать, замерять время — делай это в прокси, не трогая священный реальный объект. Чистота кода, сука!
Вот и весь паттерн. Не заместитель, а такой управдом, который всем заправляет. Удобная хуйня, если использовать с умом.