Шаблоны программирования на Swift: Facade
Тема сегодняшней статьи из цикла шаблоны программирования на Swift — шаблон Facade
Facade
Многие сложные системы состоят из огромной кучи компонент. Так же и в жизни, очень часто для совершения одного основного действия, мы должны выполнить много маленьких.
К примеру, чтобы пойти в кино нам надо:
-
Посмотреть расписание фильмов, выбрать фильм, посмотреть когда есть сеансы, посмотреть когда у нас есть время.
- Необходимо купить билет, для этого ввести номер карточки, секретный код, дождаться снятия денег, распечатать билет.
-
Приехать в кинотеатр, припарковать машину, купить попкорн, найти места, смотреть.
И все это для того, чтобы просто посмотреть фильм, который нам, очень вероятно, не понравится.
Или же возьмем пример Amazon – покупка с одного клика – как много систем задействовано в операции покупки? И проверка Вашей карточки, и проверка Вашего адреса, проверка товара на складе, проверка или возможна доставка даного товара в даную точку мира… В результате очень много действий которые происходят всего по одному клику.
Для таких вот процесов был изобретен паттерн – Фасад ( Facade ) который предоставляет унифицированный интерфейса к большому количеству интерфейсов системы, в следствии чего систему стает гораздо проще в использовании.
Давайте, попробуем создать систему которая нас переносит в другую точку мира с одного нажатия кнопки! Сначала нам нужна система, которая проложит путь от нашего места перебывания в место назначения:
// // proSwift.ru // class Pathfinder { func findCurrentLocation() { print("Ищем местоположение... О! Вот ты где!") } func findLocationToTravel(location: String) { print("Итак, ты хочешь переместиться в \(location)") } func maeARoute() { print("Отлично! Для путешествия будем заглядывать на Яндекс карты...") } }
Так же нам необходима сама система заказа транспорта и собственно путешествия:
// // proSwift.ru // class TravelEngene { func findTransport() { print("Для путешествия нужны ездовые собаки") } func orderTransport() { print("Дайте вот тех, которые в упряжке...") } func travel() { print("Ю-ху! В путь!") } }
Ну и какие же путешествия без билетика:
// // proSwift.ru // class TicketPrintingSystem { func createTicket() { print("Ожидание ответа от базы...") } func printTicket() { print("Ответ получен! На собаках? Не забудь покормить их...") } }
А теперь, давайте создадим единый доступ ко всем этим системам:
// // proSwift.ru // class TravelSystemFacade { func travelTo(aLocation: String) { let pf = Pathfinder() let te = TravelEngene() let tp = TicketPrintingSystem() pf.findCurrentLocation() pf.findLocationToTravel(aLocation) pf.maeARoute() te.findTransport() te.orderTransport() tp.createTicket() tp.printTicket() te.travel() } }
Фасад знает все про все системы, потому в одном методе он берет и транспортирует нас куда следует. Код теста элементарен:
// // proSwift.ru // let facade = TravelSystemFacade() facade.travelTo("Лондон")
Консоль отобразит весь процесс путешествия, которое мы вызвали одним методом нашего фасада.
Ищем местоположение... О! Вот ты где! Итак, ты хочешь переместиться в Лондон Отлично! Для путешествия будем заглядывать на Яндекс карты... Для путешествия нужны ездовые собаки Дайте вот тех, которые в упряжке... Ожидание ответа от базы... Ответ получен! На собаках? Не забудь покормить их... Ю-ху! В путь!
Пример с GitHub
Еще раз:
Шаблон фасад используется для определения простого интерфейса к более сложной подсистеме.
// // proSwift.ru // // https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/source/structural/facade.swift enum Eternal { static func setObject(value: AnyObject!, forKey defaultName: String!) { let defaults:NSUserDefaults = NSUserDefaults.standardUserDefaults() defaults.setObject(value, forKey:defaultName) defaults.synchronize() } static func objectForKey(defaultName: String!) -> AnyObject! { let defaults:NSUserDefaults = NSUserDefaults.standardUserDefaults() return defaults.objectForKey(defaultName) } } Eternal.setObject("Disconnect me. I’d rather be nothing", forKey:"Bishop") Eternal.objectForKey("Bishop")
Шаблоном программирования Фасад определены два метода для записи объектов по ключу в NSUserDefaults и их получении. Громоздкий код заменяется одной строкой.
Скажите пожалуйста, почему вы используете enum для Eternal а не допустим class или struct?
Я думаю, что в данном конкретном случае программист использовал enum потому что мог. Дело в том, что в очень не большом количестве языков программирования есть возможность добавлять полноценные методы к перечислениям.
А если обратится к теории, то картина следующая:
Enum: перечисления представляют собой конечное число «состояний бытия» (случаев). Перечисления инициализируются случаем (кейсом перечисления) и эти случаи всегда должны быть действительными экземплярами.
Structs следует использовать, когда не существует конечного числа действительных экземпляров, которые также не образуют полного определения объекта
Классы полностью определяют первичный параметры объекта в вашей модели, ее атрибуты и методы внутреннего и внешнего взаимодействия.