Ответ
Оба паттерна относятся к структурным, но решают разные проблемы.
Proxy (Заместитель)
- Цель: Контроль доступа к объекту, добавление логики (ленивая загрузка, кэширование, защита, логирование) без изменения его основного кода.
- Структура: Прокси и реальный объект реализуют один и тот же интерфейс. Клиент работает с прокси, который делегирует вызовы реальному объекту при необходимости.
- Пример (Ленивая загрузка изображения):
protocol Image { func display() }
class RealImage: Image { init(filename: String) { / Дорогая загрузка с диска / } func display() { print("Отображение изображения") } }
class ProxyImage: Image { private let filename: String private lazy var realImage: RealImage = RealImage(filename: filename) // Ленивая инициализация
init(filename: String) { self.filename = filename }
func display() { realImage.display() } // Реальный объект создаётся только здесь
}
// Использование let image: Image = ProxyImage(filename: "photo.jpg") image.display() // RealImage загружается и отображается только в этот момент
### Bridge (Мост)
* **Цель:** Разделить абстракцию (интерфейс) и её реализацию, чтобы они могли изменяться независимо. Позволяет избежать наследования в виде "кубика Lego".
* **Структура:** Абстракция содержит ссылку на объект реализации (через общий протокол). Можно комбинировать разные абстракции с разными реализациями.
* **Пример (Графические примитивы и рендереры):**
```swift
// Реализация
protocol Renderer {
func renderCircle(radius: Float)
}
class VectorRenderer: Renderer {
func renderCircle(radius: Float) { print("Рисуем круг линиями (радиус: (radius))") }
}
class RasterRenderer: Renderer {
func renderCircle(radius: Float) { print("Рисуем круг пикселями (радиус: (radius))") }
}
// Абстракция
class Shape {
let renderer: Renderer
init(renderer: Renderer) { self.renderer = renderer }
func draw() {}
}
class Circle: Shape {
let radius: Float
init(radius: Float, renderer: Renderer) {
self.radius = radius
super.init(renderer: renderer)
}
override func draw() {
renderer.renderCircle(radius: radius) // Делегирование реализации
}
}
// Использование
let vectorCircle = Circle(radius: 5, renderer: VectorRenderer())
let rasterCircle = Circle(radius: 10, renderer: RasterRenderer())
vectorCircle.draw() // Рисуем круг линиями (радиус: 5.0)
rasterCircle.draw() // Рисуем круг пикселями (радиус: 10.0)
Итог: Proxy управляет доступом к одному объекту, Bridge разделяет иерархии абстракции и реализации.