Зачем нужен?
Паттерн Facade применяется, когда какой-то части клиента требуется упрощенный интерфейс, управляющий полной функциональностью сложной подсистемы.
Определение
- предоставляет унифицированный интерфейс к группе интерфейсов подсистемы. Фасад определяет высокоуровневый интерфейс, упрощающий работу с подсистемой
- обертывает(упаковывает) сложную подсистему в простой интерфейс
Реализация
Паттерн инкапсулирует сложную подсистему внутри одного простого интерфейса. Упрощает начальное использование подсистемы(при этом остается гибкость, если нужна сложная настройка), уменьшает связанность. К реализации нужно подходить осторожно - фасад легко превратить в god-объект, который управляет всем и вся.
Реализация похожа на паттерн адаптер, но задачи у них разные.
- Определите упрощенный интерфейс для подсистемы/компонента
- Спроектируйте класс-обертку(фасад), реализующий этот интерфейс
- Фасад управляет сложностью и взаимодействием компонентов с помощью делегации методов
- Клиент использует(связан) с фасадом
Пример
Допустим у нас сложная система домашнего кинотеатра: проектор, усилитель, cd-плеер, экран, освещение..
Чтобы все это включить надо потратить много времени. Вместо этого, определим упрощенный интерфейс: watchMovie() и endMovie.
Реализуем класс-обертку(фасад):
// фасад
class HomeTheaterFacade {
// компоненты подсистемы, которые будет использовать фасад
private let ampifier: Ampifier
private let tuner: Tuner
private let cdPlayer: CDPlayer
private let projector: Projector
private let theaterLights: TheaterLights
private let screen: Screen
private let popcornPopper: PopcornPopper
init(ampifier: Ampifier, tuner: Tuner, cdPlayer: CDPlayer,
projector: Projector, theaterLights: TheaterLights,
screen: Screen, popper: PopcornPopper) {
self.ampifier = ampifier
self.tuner = tuner
self.cdPlayer = cdPlayer
self.projector = projector
self.theaterLights = theaterLights
self.screen = screen
self.popcornPopper = popper
}
func watchMovie(movie: String) {
}
func endMovie() {
}
}
С помощью делегации определим взаимодействие компонентов
func watchMovie(movie: String) {
print("Get ready to watch \(movie)")
popcornPopper.on()
popcornPopper.pop()
theaterLights.dim()
screen.down()
projector.on()
projector.wideScreenModeOn()
ampifier.on()
ampifier.setCD()
ampifier.setVolume()
cdPlayer.on()
cdPlayer.play()
}
func endMovie() {
print("Shutting down")
popcornPopper.off()
screen.up()
projector.off()
ampifier.off()
cdPlayer.off()
}
Дальше клиент использует класс-фасад HomeTheaterFacade и наслаждается просмотром фильмов.
В качестве другого примера - звонок в интернет магазин для заказа товара. Клиент взаимодействует с упрощенным интерфейсом(оператором), который заполняет заказ, форму оплаты, адрес доставки и тд.