Ответ
Singleton — гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к нему.
class Singleton private constructor() {
companion object {
@Volatile
private var instance: Singleton? = null
fun getInstance(): Singleton {
return instance ?: synchronized(this) {
instance ?: Singleton().also { instance = it }
}
}
}
}
Использование:
val singleton = Singleton.getInstance()
Плюсы:
- Контроль доступа к единственному экземпляру.
- Ленивая инициализация (экземпляр создаётся только при первом вызове).
Минусы:
- Усложняет тестирование из-за глобального состояния.
- Нарушает принцип единственной ответственности.
Ответ 18+ 🔞
Давай разберем эту вашу одинокую сущность, этот паттерн Singleton. Представь себе, что ты — единственный унитаз на весь офисный этаж. Все ходят к тебе, ты всем нужен, и ты должен быть один. Вот это и есть Синглтон, ёпта.
Вот смотри, как это выглядит в коде, прям классика жанра:
class Singleton private constructor() {
companion object {
@Volatile
private var instance: Singleton? = null
fun getInstance(): Singleton {
return instance ?: synchronized(this) {
instance ?: Singleton().also { instance = it }
}
}
}
}
Что тут происходит, ядрёна вошь? private constructor() — это чтобы всякие умники не лезли со своими new Singleton(). Хуй с горы, а не публичный конструктор! Создать экземпляр можно только через getInstance(). А внутри — вся эта синхронизация и проверка @Volatile, чтобы в многопоточке не вышло, что два потока одновременно создадут два экземпляра. Это как если бы два человека вломились в единственную кабинку — пиздопроебибна получится, а не работа.
Как этим пользоваться? Да элементарно!
val singleton = Singleton.getInstance()
Всё. Больше нигде не new, нигде не создаём. Берём один готовый экземпляр и таскаем его по всему приложению, как чемодан без ручки.
Ну и что он нам дает, этот самый Синглтон?
- Контроль доступа к единственному экземпляру. Ты точно знаешь, что этот объект в единственном числе, как последняя пельмешка в тарелке. Все изменения в нём видны отовсюду.
- Ленивая инициализация. Объект создастся не когда приложение стартанёт, а только когда кто-то первый раз лениво скажет «дай-ка я его получу». Пока не спросили — живи спокойно, ресурсы не жри.
А теперь минусы, и они овердохуища серьёзные:
- Тестирование превращается в ад. Потому что этот объект — глобальное состояние. Протестировал ты его в одном тесте, он поменялся, а следующий тест уже на подпорченных данных работает. Доверия ебать ноль к результатам таких тестов.
- Нарушает принцип единственной ответственности. Класс начинает заниматься не только своей прямой работой, но и ебётся с контролем над своим жизненным циклом. Это как если бы унитаз сам решал, когда его чистить. Мудя полная.
- Скрытая зависимость. Классы, которые используют синглтон, не объявляют эту зависимость явно в конструкторе. Она просто берётся из воздуха. Подозрение ебать чувствую к такому коду.
Короче, паттерн как будто простой, но вы ходите по охуенно тонкому льду. Часто его используют там, где можно было бы обойтись нормальной зависимостью через DI-контейнер. Используй с умом, а то получится хитрая жопа, которую потом год распутывать.