Почему использовать shared instance для хранения состояния в приложении
Что проверяют
Понимаете ли вы, что синглтон это не удобство, а размен: единая точка истины в обмен на глобальное изменяемое состояние. Интервьюер смотрит, назовёте ли вы цену честно и отличаете ли случаи, где shared уместен, от случаев, где им затыкают отсутствие архитектуры.
Как отвечать
Начните с задачи, которую решает shared instance: некоторые сущности по своей природе одна на процесс, и второй экземпляр означал бы рассинхронизацию. Так устроены UserDefaults.standard, FileManager.default, URLSession.shared, так же обычно живут сессия пользователя, кэш и слой аналитики.
В Swift это выглядит так:
final class UserSession {
static let shared = UserSession()
private init() {}
private(set) var token: String?
}static let инициализируется лениво и ровно один раз, потокобезопасно, без ручных блокировок. private init() закрывает создание второго экземпляра, без него это просто глобальная переменная.
Дальше сразу назовите ограничения и способ их снять. Изменяемое состояние внутри синглтона требует синхронизации: очередь, блокировка или actor, иначе будут гонки. Сама зависимость от глобального объекта прячется внутри классов, поэтому сильный вариант такой: объявить протокол, передавать реализацию через инициализатор, а shared трогать только в точке сборки приложения. Тогда тест подставит свою реализацию, а продакшен получит единственный экземпляр.
Где спотыкаются
Объясняют выбор экономией памяти. Разница между одним объектом и несколькими это единицы килобайт, ради такого архитектуру не меняют. Настоящий мотив другой: единая точка истины и контроль доступа к общему ресурсу.
Забывают private init() и оставляют свойства открытыми на запись. Класс, у которого любой код может создать второй экземпляр или переписать поле извне, не даёт ни одной из обещанных гарантий.
Недооценивают эффект в тестах. Состояние синглтона переживает тест, и результат начинает зависеть от порядка запуска: по отдельности зелено, всем набором красно. Лечится сбросом состояния в setUp или тем, что тестируемый класс получает зависимость снаружи, а не тянет shared сам.