> В чем разница паттернов 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:

SWIFT
protocol Device {
var volume: Int { get set }
func turnOn()
func turnOff()
}
class TV: Device {
var volume = 50
func turnOn() { print("TV on") }
func turnOff() { print("TV off") }
}
class Radio: Device {
var volume = 30
func 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: Device
init(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:

SWIFT
protocol ImageLoading {
func loadImage() -> UIImage
}
class RealImageLoader: ImageLoading {
private let url: URL
init(url: URL) { self.url = url }
func loadImage() -> UIImage {
// реальная загрузка
return UIImage()
}
}
class LazyImageProxy: ImageLoading {
private let url: URL
private 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 = image
return image
}
}
// Клиент не знает, что работает с Proxy
let 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.
  • Слишком абстрактный ответ без примеров из реальной разработки - интервьюер ждет конкретики.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью