Что такое паттерн Proxy (Заместитель)?

Ответ

Proxy — это структурный паттерн, предоставляющий объект-заместитель, который контролирует доступ к другому объекту. Заместитель имеет тот же интерфейс, что и реальный объект, позволяя выполнять дополнительные действия до или после обращения к нему.

Цель: Контроль доступа к объекту, ленивая инициализация, кеширование, логирование без изменения его кода.

Основные виды Proxy:

  • Виртуальный (Virtual Proxy): Откладывает создание ресурсоемкого объекта до момента реального использования.
  • Защищающий (Protection Proxy): Контролирует права доступа к объекту.
  • Удаленный (Remote Proxy): Представляет объект, находящийся в другом адресном пространстве (например, на сервере).
  • Логирующий (Logging Proxy): Записывает вызовы методов.

Пример (Виртуальный Proxy для изображения):

// 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("Загрузка изображения с диска: " + filename);
    }

    @Override
    public void display() {
        System.out.println("Отображение изображения: " + 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 Demo {
    public static void main(String[] args) {
        Image image = new ProxyImage("photo.jpg");
        // RealImage еще не создан
        image.display(); // Создаст RealImage и вызовет display()
        image.display(); // Повторно использует существующий RealImage
    }
}

Ответ 18+ 🔞

А, паттерн Proxy, ну это же классика, ёпта! Представь себе, что ты — важная шишка, и к тебе на приём все ломятся. Но ты же не будешь с каждым встревать в разговор, блядь? Ты поставишь секретаршу, которая будет фильтровать: кого пустить, кого послать нахуй, а кому сказать, что ты в отпуске. Вот эта секретарша — и есть прокси, сука!

Цель у неё простая: контролировать доступ к тебе, лениво инициализироваться (то есть не вставать с кресла, пока реально не надо), кешировать ответы и логировать, кто и зачем приходил, — и всё это без изменения твоего, блядь, драгоценного кода.

Основные виды этих секретарш-прокси:

  • Виртуальная (Virtual Proxy): Та, которая тебя будит только когда клиент реально, внатуре, приперся. Пока его нет — ты спишь, ресурсы не тратишь.
  • Защищающая (Protection Proxy): Та, которая смотрит у клиента пропуск. Нет пропуска — получи в ебало и иди нахуй.
  • Удаленная (Remote Proxy): Та, которая представляет тебя, когда ты сидишь на другом конце света, на сервере. Она за тебя все разговоры ведёт.
  • Логирующая (Logging Proxy): Та, которая всё записывает в блокнотик: "Такой-то приходил, хотел вот это, я ему сказала то-то".

Смотри, как это выглядит в коде, на примере картинки, которую лень грузить:

// 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("Загрузка изображения с диска: " + filename); // Тяжело, блядь!
    }

    @Override
    public void display() {
        System.out.println("Отображение изображения: " + 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 Demo {
    public static void main(String[] args) {
        Image image = new ProxyImage("photo.jpg"); // Создали прокси, а реальная картинка? А её нет ещё!
        // RealImage ещё не создан, мы даже не слышали этот долгий звук загрузки с диска
        image.display(); // Опа! Вот тут прокси создаст RealImage и вызовет display()
        image.display(); // А тут уже всё готово, просто повторно использует существующую картинку. Красота!
    }
}

Вот и весь фокус, ебать мои старые костыли! Прокси делает вид, что он и есть объект, но на самом деле он просто хитрая обёртка, которая решает, когда и как к реальному объекту обращаться. Удобно, как хуй с винтом!