Перейти к основному содержимому

Что это такое

Паттерн Proxy ставит перед настоящим объектом заместителя с тем же интерфейсом. Вызывающий код обращается к заместителю так, будто это и есть настоящий объект; заместитель сам решает, когда и как задействовать оригинал.

Обычные задачи такого заместителя: кэширование ответов, проверка прав доступа, откладывание дорогого создания объекта, подсчёт вызовов.

Примечание: называйте класс по его задаче — CachedWeather, ReadOnlyAccount — но никогда не Proxy. Это имя уже занято встроенным объектом JavaScript.


Пример: кэширующий заместитель

Настоящий сервис погоды работает медленно. Заместитель отвечает на повторные вопросы из своего кэша Map и обращается к сервису только за новыми — и всё это за тем же самым интерфейсом Weather.

Заместитель, который запоминает

Первый вопрос про Paris доходит до удалённого сервиса; на второй отвечает кэш — строка (обращаемся к удалённому сервису...) печатается только один раз, а второй ответ заканчивается на (из кэша).

Prompt
Напишите программу на TypeScript с кэширующим заместителем: интерфейс Weather с методом forecast, класс WeatherService, который печатает сообщение при обращении к удалённому сервису, и класс-заместитель CachedWeather, который хранит ответы в Map и отдаёт повторные запросы из кэша. Запросите один и тот же город дважды и напечатайте оба ответа.
Вывод: программа на TypeScript и захваченный вывод

Когда его использовать

Используйте его, чтобы добавить кэширование, контроль доступа, ленивую загрузку или учёт вызовов перед тем, что вы не можете или не должны менять — особенно перед удалёнными или дорогими ресурсами.

Откажитесь от него, когда объект принадлежит вам и поведение должно находиться внутри него. Proxy нужен для управления доступом; Decorator — для добавления поведения слоями; выбирайте тот замысел, который подходит.


Плюсы и минусы

Плюсы: вызывающему коду вообще не нужно меняться — интерфейс остаётся прежним; дорогая работа пропускается или контролируется в одном месте.

Минусы: скрытое поведение — вызывающий код может получить ответ из кэша, не зная об этом; устаревший кэш и неожиданные отказы приходится отлаживать за внешне безобидным интерфейсом.