Приведи пример реализации паттерна Фасад (Facade) в Swift.

Ответ

Фасад (Facade) — это структурный паттерн, который предоставляет простой, унифицированный интерфейс к сложной подсистеме, скрывая ее внутренние детали. Он упрощает использование системы для клиента.

Проблема: Клиентскому коду приходится взаимодействовать с множеством разнородных классов подсистемы, знать их API и порядок вызова.

Решение: Фасад инкапсулирует сложность, предоставляя один удобный метод.

Пример: Система домашнего кинотеатра

Сложная подсистема (классы, которые нужно скрыть):

class Projector {
    func on() { print("Projector: ON") }
    func off() { print("Projector: OFF") }
    func setInput(_ source: String) { print("Projector input set to: (source)") }
}

class AudioAmplifier {
    func on() { print("Amplifier: ON") }
    func off() { print("Amplifier: OFF") }
    func setVolume(_ level: Int) { print("Amplifier volume set to: (level)") }
    func setSurroundSound() { print("Amplifier: Surround sound ON") }
}

class BluRayPlayer {
    func on() { print("BluRay Player: ON") }
    func off() { print("BluRay Player: OFF") }
    func play(movie: String) { print("BluRay Player: Playing '(movie)'") }
}

class Lights {
    func dim(_ percentage: Int) { print("Lights dimmed to (percentage)%") }
}

Фасад, упрощающий взаимодействие:

class HomeTheaterFacade {
    private let projector: Projector
    private let amplifier: AudioAmplifier
    private let player: BluRayPlayer
    private let lights: Lights

    init(projector: Projector, amplifier: AudioAmplifier,
         player: BluRayPlayer, lights: Lights) {
        self.projector = projector
        self.amplifier = amplifier
        self.player = player
        self.lights = lights
    }

    // Простой метод, скрывающий сложность настройки системы
    func watchMovie(_ movieName: String) {
        print("n=== Getting ready to watch '(movieName)' ===")
        lights.dim(10)
        projector.on()
        projector.setInput("BluRay")
        amplifier.on()
        amplifier.setSurroundSound()
        amplifier.setVolume(8)
        player.on()
        player.play(movie: movieName)
        print("=== Enjoy the movie! ===n")
    }

    // Другой простой метод для выключения всего
    func endMovie() {
        print("n=== Shutting down the home theater ===")
        player.off()
        amplifier.off()
        projector.off()
        lights.dim(100)
    }
}

Использование клиентом:

// 1. Инициализация подсистемы (может быть сложной)
let projector = Projector()
let amplifier = AudioAmplifier()
let player = BluRayPlayer()
let lights = Lights()

// 2. Создание фасада
let homeTheater = HomeTheaterFacade(projector: projector,
                                    amplifier: amplifier,
                                    player: player,
                                    lights: lights)

// 3. Клиент использует простой интерфейс фасада
homeTheater.watchMovie("Inception")
// ... просмотр фильма ...
homeTheater.endMovie()

Вывод программы:

=== Getting ready to watch 'Inception' ===
Lights dimmed to 10%
Projector: ON
Projector input set to: BluRay
Amplifier: ON
Amplifier: Surround sound ON
Amplifier volume set to: 8
BluRay Player: ON
BluRay Player: Playing 'Inception'
=== Enjoy the movie! ===

=== Shutting down the home theater ===
BluRay Player: OFF
Amplifier: OFF
Projector: OFF
Lights dimmed to 100%

Преимущества паттерна Фасад:

  • Упрощает использование: Клиенту нужно знать только один класс (Фасад).
  • Снижает связанность: Клиент не зависит от множества классов подсистемы.
  • Не заставляет использовать: Клиент по-прежнему может обращаться к классам подсистемы напрямую, если это необходимо.

Ответ 18+ 🔞

Э, слушай, смотри, есть такая хуйня — паттерн Фасад. Представь себе, ты купил нахуй целый домашний кинотеатр: проектор, усилитель, синий-рей плеер, свет. И чтобы фильм посмотреть, тебе надо каждую эту хуйню включать в правильном порядке, иначе нихуя не заработает. Волнение ебать! А если ты ещё и выпивший, то вообще пиздец.

Вот Фасад — это такой мужик-управдом для всей этой сложной системы. Он знает, какую кнопку когда жать. Ты ему говоришь: «Вася, давай „Начало“ посмотрим», а он уже сам всё сделает: свет притушит, проектор зажжёт, звук окружной включит. Красота!

Без фасада пришлось бы писать код, который выглядит как инструкция для идиота:

lights.dim(10)
projector.on()
projector.setInput("BluRay")
amplifier.on()
amplifier.setSurroundSound()
amplifier.setVolume(8)
player.on()
player.play(movie: "Inception")

Сука, да я пока всё это пропишешь, уже и смотреть расхочется! А с фасадом — одна строчка, и похуй:

homeTheater.watchMovie("Inception")

Вот и весь паттерн. Он не запрещает тебе лезть в подсистему и ковыряться в ней вилкой, если охота приключений. Но для 99% случаев — просто вызвал метод фасада и пошёл попкорн жарить. Упрощает жизнь, снижает связанность, в общем, ёпта, полезная штука. Чистая инкапсуляция, блядь. В рот меня чих-пых!