> В чем разница паттернов Bridge и Proxy (iOS, Swift)
Уровень: senior · Роль: mobile · Категория: Технические вопросы
Компании: Bip.ru
Стек: iOS, Swift
> Пример ответа
Короткий ответ
Bridge и Proxy решают разные задачи. Bridge разделяет абстракцию и реализацию, позволяя им изменяться независимо. Proxy контролирует доступ к реальному объекту, добавляя дополнительную логику без изменения его интерфейса. Bridge - структурный паттерн для проектирования иерархий, Proxy - для управления жизненным циклом, ленивой загрузкой, кешированием или защитой. В iOS Bridge часто применяется для оборачивания UIKit в собственные абстракции, Proxy - для DI-контейнеров или remote-объектов.
Подробное объяснение
Bridge - это паттерн, который разделяет абстракцию (что делает объект) и реализацию (как он это делает) на две независимые иерархии. Классический пример: абстракция RemoteControl и реализация Device. Вы можете менять пульты и устройства независимо, комбинируя их.
Proxy - это суррогат, который контролирует доступ к другому объекту. Proxy реализует тот же интерфейс, что и реальный объект, но перехватывает вызовы для добавления логики: ленивая инициализация, кеширование, проверка прав, логирование, сетевое взаимодействие.
Ключевые различия:
- Назначение: Bridge - структурное разделение, Proxy - контроль доступа.
- Иерархия: Bridge создает две параллельные иерархии, Proxy - один интерфейс и один реальный объект.
- Прозрачность: Proxy полностью прозрачен для клиента (клиент не знает, что работает с Proxy), Bridge - клиент осознанно работает с абстракцией.
- Изменяемость: Bridge позволяет менять реализацию во время выполнения, Proxy - обычно фиксирует реальный объект.
- Связь с объектом: Bridge - композиция (абстракция содержит реализацию), Proxy - делегирование (Proxy содержит ссылку на реальный объект).
На практике
В iOS-разработке Bridge часто используется для создания слоя абстракции над UIKit или SwiftUI, чтобы тестировать логику без UI. Например, протокол ViewControlling с реализациями UIKitViewController и SwiftUIViewController.
Proxy применяется в:
- ленивой загрузке тяжелых ресурсов (изображения, данные);
- кешировании сетевых запросов;
- защите от нежелательного доступа (например, проверка авторизации);
- работе с remote-объектами (NSProxy для distributed objects).
Для мобильного разработчика важно понимать, что Proxy часто реализуется через NSProxy или просто через обертку с тем же протоколом. Bridge - через протоколы и композицию.
Пример кода
Bridge:
SWIFTprotocol Device {var volume: Int { get set }func turnOn()func turnOff()}class TV: Device {var volume = 50func turnOn() { print("TV on") }func turnOff() { print("TV off") }}class Radio: Device {var volume = 30func turnOn() { print("Radio on") }func turnOff() { print("Radio off") }}protocol Remote {var device: Device { get set }func volumeUp()func volumeDown()}class BasicRemote: Remote {var device: Deviceinit(device: Device) { self.device = device }func volumeUp() { device.volume += 1 }func volumeDown() { device.volume -= 1 }}// Использованиеlet tv = TV()let remote = BasicRemote(device: tv)remote.volumeUp()
Proxy:
SWIFTprotocol ImageLoading {func loadImage() -> UIImage}class RealImageLoader: ImageLoading {private let url: URLinit(url: URL) { self.url = url }func loadImage() -> UIImage {// реальная загрузкаreturn UIImage()}}class LazyImageProxy: ImageLoading {private let url: URLprivate var realLoader: RealImageLoader?private var cachedImage: UIImage?init(url: URL) { self.url = url }func loadImage() -> UIImage {if let cached = cachedImage { return cached }if realLoader == nil {realLoader = RealImageLoader(url: url)}let image = realLoader!.loadImage()cachedImage = imagereturn image}}// Клиент не знает, что работает с Proxylet loader: ImageLoading = LazyImageProxy(url: url)let image = loader.loadImage()
Как отвечать на собеседовании
Начните с краткого определения обоих паттернов, затем переходите к сравнению по ключевым критериям: цель, структура, прозрачность для клиента. Обязательно приведите пример из iOS-практики - это покажет, что вы не просто заучили теорию. Упомяните, что Bridge решает проблему "разрастания классов" при комбинации вариантов, а Proxy - проблему "дорогого доступа" к объекту. Если спросят про сходства - оба используют композицию и делегирование, оба скрывают детали, но с разными целями.
Что проверяет интервьюер
Интервьюер оценивает:
- понимание назначения паттернов, а не только их структуру;
- способность различать похожие паттерны по цели, а не по коду;
- умение применять паттерны в контексте iOS (UIKit, SwiftUI, сетевой слой);
- знание trade-off: Bridge добавляет гибкость, но усложняет иерархию; Proxy добавляет прослойку, но может скрыть реальную стоимость операций.
Типичные ошибки
- Путаница с Adapter: Adapter меняет интерфейс, Proxy сохраняет его, Bridge - создает новый уровень абстракции.
- Утверждение, что Proxy - это всегда ленивая загрузка. На самом деле есть защитные, кеширующие, remote-прокси.
- Попытка объяснить Bridge через наследование - это ошибка, Bridge всегда использует композицию.
- Игнорирование контекста: в iOS часто путают Proxy с Delegate или с обертками для DI. Delegate - это другой паттерн, а DI-обертки - это фабрики, не Proxy.
- Слишком абстрактный ответ без примеров из реальной разработки - интервьюер ждет конкретики.
> Похожие задачи по mobile
Как реализовать удаление нескольких элементов при ограничении бэкенда на один запрос на удаление
Какие проблемы с многопоточностью существуют, например race condition, data race, starvation, priority inversion, deadlock
Как решить проблему тестирования синглтона с использованием моков
В чем разница фабрики и билдера
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью