iOS Подготовка к собеседованию 5 — Одиночки
Одноэлементный шаблон — это шаблон проектирования, который гарантирует, что класс имеет только один экземпляр, и предоставляет глобальную точку доступа к этому экземпляру. Это может быть полезно, когда класс необходимо использовать в нескольких частях приложения, но создавать несколько экземпляров класса нецелесообразно или нежелательно. В iOS шаблон singleton является широко используемым шаблоном проектирования.
Вопросы для интервью
- Что такое Singleton и как его использовать в iOS-разработке?
- Можете ли вы объяснить шаблон проектирования Singleton и его преимущества?
- Каковы возможные способы предотвращения нескольких экземпляров Singleton в многопоточной среде?
- Можете ли вы привести пример использования Singleton в своем приложении для iOS?
- Как вы тестируете Singleton в iOS?
Одной из частых проблем с синглтонами является то, что часто они не потокобезопасны. Они часто используются с нескольких контроллеров, одновременно обращающихся к экземпляру singleton.
При создании синглтона необходимо учитывать две вещи.
- Экземпляр должен быть создан с точки зрения безопасности потоков.
- Вы должны пометить метод init класса как закрытый, чтобы предотвратить создание дополнительных экземпляров.
- Во время инициализации экземпляра singleton.
- Во время чтения и записи в экземпляр.
Чтобы реализовать шаблон синглтона в Swift, класс, который должен быть синглтоном, определяется с помощью static
ключевого слова, которое указывает, что класс имеет только один экземпляр. Статическая переменная используется для хранения экземпляра класса, а статический метод используется для доступа к экземпляру. Вот пример одноэлементного класса в Swift.
class Singleton {
// Swift guarantees initialization is atomic
// Swift treats the code performing initialization as a critical section
static let shared = Singleton()
// prevents the creation of additional instances of the class.
private init() {}
}
let singleton = Singleton.shared
@implementation MySingleton
// Lazy initializer
+ (instancetype)sharedInstance {
static dispatch_once_t once;
static id sharedInstance;
// The token ensures that init is executed only once in thread safety manner
dispatch_once(&once, ^{
_sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
// Prevent creating new instance of the singleton
- (instancetype)init __attribute__((unavailable("Use +[MyClass sharedInstance] instead")));
+ (instancetype)new __attribute__((unavailable("Use +[MyClass sharedInstance] instead")));
@end
Плюсы
- Гарантирует создание только одного экземпляра класса, что помогает экономить память и повышать производительность.
- Предоставляет глобальную точку доступа к экземпляру класса, что упрощает его использование в коде.
- Может быть полезно для реализации общих ресурсов, таких как базы данных или сетевые подключения, которые должны быть общими для разных частей вашего кода.
- Может затруднить тестирование и отладку вашего кода, поскольку вводит глобальное состояние, совместно используемое различными частями вашего кода.
- Затрудняет создание нескольких экземпляров класса для тестирования или других целей.
- Может привести к жесткой связи и нарушить принципы объектно-ориентированного проектирования.
- Не лучший вариант для любых задач, связанных с сеансом пользователя, так как вам может потребоваться уничтожить и создать новый синглтон, когда пользователь выходит из системы.
Существует гарантия 1 на учетную запись (а не гарантия на одно приложение). Доступ не глобальный (нужна пользовательская сессия). Подобно синглтону, лениво создается при первом доступе, впоследствии всегда возвращается один и тот же экземпляр. Например, MyUserSession создается, когда аутентифицированный пользователь начинает сеанс. Он должен быть внедрен в любой код, содержащий пользовательские данные.