Шаблоны программирования на Swift: Bridge
Тема сегодняшней статьи из цикла шаблоны программирования на Swift — шаблон Bridge.
Bridge
Книга вешает:
Представьте себе, что у нас есть что-то однотипное, к примеру у нас есть телефон и куча наушников. Если бы у каждого телефона был свой разъем, то мы могли бы пользоваться только одним типом наушников. Но Бог миловал! Собственно таже штука и с наушникам. Они могут выдавать различный звук, иметь различные дополнительные функции, но основная их цель – просто звучание:) И хорошо, что во многих случаях штекер у них одинаковый (я не говорю про различные студийные наушники:) ).
Собственно, Мост (Bridge) позволяет разделить абстракцию от реализации, так чтобы реализация в любой момент могла быть поменяна, не меняя при этом абстракции.
Когда использовать?
-
Вам совершенно не нужна связь между абстракцией и реализацией.
- Собственно, как абстракцию так и имплементацию могут наследовать независимо.
-
Вы не хотите чтобы изменения в реализации имело влияния на клиентский код.
Рассмотрим пример:
Создадим базовый класс для наушников со своим функционалом:
// // proSwift.ru // class BaseHeadphones { func playSimpleSound(){ print("Пш..") } func playBassSound() { print("Пш..") } }
И его наследников — дорогие и дешевые наушники:
// // proSwift.ru // class CheapHeadphones: BaseHeadphones { override func playSimpleSound() { print("Бип-бип пшшшшшшш") } override func playBassSound() { print("Бух-Бух прррр") } } class ExpensiveHeadphones: BaseHeadphones { override func playSimpleSound() { print("Бип-Бип-Бип Тарам-пам-пам") } override func playBassSound() { print("Бам-бам-бам") } }
Как видите, функционал у них свой, отличающийся от базовой абстракции.
И собственно плеер, через который мы будем слушать музыку:
// // proSwift.ru // class MusicPlayer { var headPhones: BaseHeadphones? func playMusic() { headPhones?.playBassSound() headPhones?.playBassSound() headPhones?.playSimpleSound() headPhones?.playSimpleSound() } }
Как видите, одно из свойств нашего плеера – наушники. Их можно подменять в любой момент, так как свойство того же типа, от которого наши дешевые и дорогие наушники наследуются.
Теперь тест!
// // proSwift.ru // let player = MusicPlayer() let ch = CheapHeadphones() let ex = ExpensiveHeadphones() player.headPhones = ch player.playMusic() print("- - - - - - - - - - -") player.headPhones = ex player.playMusic()
Вывод в консоль:
Бух-Бух прррр Бух-Бух прррр Бип-бип пшшшшшшш Бип-бип пшшшшшшш - - - - - - - - - - - Бам-бам-бам Бам-бам-бам Бип-Бип-Бип Тарам-пам-пам Бип-Бип-Бип Тарам-пам-пам
Как видно, все работает нормально. Наушники меняются и меняют функционал, при этом базовая абстракция у нас неизменна.
Пример с GitHub
Еще раз:
Шаблон Мост используется для разделения абстрактных элементов класса от деталей реализации, предоставляя средства для замены деталей реализации без изменения абстракции.
// // proSwift.ru // // https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/source/structural/bridge.swift protocol Switch { var appliance: Appliance {get set} func turnOn() } protocol Appliance { func start() } class RemoteControl: Switch { var appliance: Appliance func turnOn() { self.appliance.start() } init(appliance: Appliance) { self.appliance = appliance } } class TV: Appliance { func start() { print("tv turned on"); } } class VacuumCleaner: Appliance { func start() { print("vacuum cleaner turned on") } } var tvRemoteControl = RemoteControl(appliance: TV()) tvRemoteControl.turnOn() // tv turned on var fancyVacuumCleanerRemoteControl = RemoteControl(appliance: VacuumCleaner()) fancyVacuumCleanerRemoteControl.turnOn() // vacuum cleaner turned on
Итак, у нас есть протокол Прибор, который описывает функционал начала работы, протокол Выключатель, который описывает свойство типа Прибор и функцию включения прибора, которая вызывает функцию начала работы. Два различных прибора — телевизор и пылесос, несомненно, разные по сути приборы, но они оба могут начинать работать, и их можно использовать в одном классе дистанционного управления. Итог — после включения обоих приборов они начали работать.
Добавить комментарий