Untitled
unknown
swift
4 years ago
3.5 kB
4
Indexable
import UIKit
let semaphore = DispatchSemaphore(value: 1)
// Класс одиночки определяет статический метод `getInstance`,
// который позволяет повторно использовать одно и то же
// подключение к APIClient по всей программе.
class APIClient {
// Конструктор одиночки всегда должен оставаться приватным,
// чтобы мы не смогли самостоятельно создавать
// экземпляры этого класса через оператор `new`.
private init() {}
// Поле для хранения объекта-одиночки должно быть объявлено статичным.
// Восклицательный знак означает, что мы гарантируем, что поле не будет nil,
// даже при учете того, что оно не задано в инициализаторе.
private static var shared: APIClient!
// Основной статический метод одиночки служит альтернативой
// конструктору и является точкой доступа к экземпляру этого
// класса.
static func getInstance() -> APIClient {
if shared == nil {
// Заставим остальные потоки дождаться создания объекта
semaphore.wait()
// На всякий случай ещё раз проверим, не был ли
// объект создан другим потоком, пока текущий
// ждал освобождения блокировки.
if shared == nil {
shared = APIClient()
}
}
// Разрешим остальным потокам продолжить выполнение
semaphore.signal()
return shared
}
// Предоставляемый функционал
func makeRequest() {
APIClientLogic.makeRequest()
}
// Создание еще одного приватного класса обусловлено
// стремлением следовать Single Responsibility Principle.
// В итоге первый класс отвечает за обеспечение единственного экземпляра,
// второй выполняет непосредственную задачу апи клиента.
// ВАЖНО: Доступа к APIClientLogic ни у кого нет. Все методы в нем статичны. Никто не сможет создать
// экземпляр APIClient, но на всякий случай даже у него мы скрываем инициализатор.
private class APIClientLogic {
private init() {}
static func makeRequest() {
/*...*/
}
}
}
// По умолчанию для каждого класса Swift предоставляет возможность использовать метод copy,
// создающий новый объект класса.
// Переопределим метод, запретив копирование объекта.
extension APIClient: NSCopying {
func copy(with zone: NSZone? = nil) -> Any {
return self
}
}
Editor is loading...