Что такое паттерн Singleton?

Ответ

Singleton — это порождающий паттерн проектирования, который гарантирует, что у класса существует только один экземпляр, и предоставляет глобальную точку доступа к нему.

Во Flutter/Dart Singleton часто используется для сервисов, менеджеров или клиентов (например, API-клиент, кэш, настройки приложения, логгер), где необходимо централизованное управление состоянием или ресурсами.

Классическая реализация на Dart:

class DatabaseConnection {
  // Статическая приватная переменная, хранящая единственный экземпляр
  static final DatabaseConnection _instance = DatabaseConnection._internal();

  // Фабричный конструктор, возвращающий единственный экземпляр
  factory DatabaseConnection() {
    return _instance;
  }

  // Приватный внутренний конструктор
  DatabaseConnection._internal() {
    // Инициализация подключения к базе данных
    print('Database connection established');
  }

  // Пример метода
  Future<void> query(String sql) async {
    // ... выполнение запроса
  }
}

void main() {
  var db1 = DatabaseConnection();
  var db2 = DatabaseConnection();
  print(identical(db1, db2)); // true — это один и тот же объект
}

Важные замечания для Flutter:

  • Ленивая инициализация: В приведённом примере экземпляр создаётся при первом обращении к DatabaseConnection() благодаря тому, как Dart инициализирует статические поля.
  • Альтернативы для управления зависимостями: В больших Flutter-приложениях вместо чистого Singleton часто используют пакеты для внедрения зависимостей (get_it, provider, riverpod), которые предоставляют более контролируемый и тестируемый способ иметь единственный экземпляр объекта в определённой области видимости.
  • Тестирование: Классический Singleton может усложнять модульное тестирование из-за глобального состояния. Использование интерфейсов и внедрение зависимостей через конструктор предпочтительнее для тестируемости.

Ответ 18+ 🔞

А, синглтон! Ну это ж классика, ёпта, как водка с огурцом. Смотри, представь ситуацию: тебе нужно, чтобы какой-то твой сервис — ну там клиент для API, менеджер кэша или ещё какая хитрая жопа — был в приложении один-единственный, как царь в голове. Чтобы куда ни ткнись, везде один и тот же экземпляр, а не чтобы каждый раз новый плодить, как мартышлюшки в зоопарке.

Вот тебе каноничный пример на Dart, смотри:

class DatabaseConnection {
  // Вот эта штука — наше всё. Статическая, приватная, хранит тот самый единственный экземпляр.
  static final DatabaseConnection _instance = DatabaseConnection._internal();

  // А это фабричный конструктор, он типа привратник. Спросишь у класса экземпляр — он тебе всегда один и тот же _instance подсунет.
  factory DatabaseConnection() {
    return _instance;
  }

  // А это наш потайной внутренний конструктор. Снаружи его не вызвать, чтоб народ не начал плодить клоны.
  DatabaseConnection._internal() {
    // Тут типа инициализация подключения к базе
    print('Database connection established');
  }

  // Ну и какой-нибудь метод для примера
  Future<void> query(String sql) async {
    // ... тут запросы всякие
  }
}

void main() {
  var db1 = DatabaseConnection();
  var db2 = DatabaseConnection();
  print(identical(db1, db2)); // Выведет true, потому что это один и тот же объект, Карл!
}

Видишь магию? Создал db1 — подключение установилось. Создал db2 — а это просто новая ссылка на тот же самый объект, второй раз уже ничего не создаётся. Удобно, блядь, как свои тапки.

Но есть нюансы, чувак, слушай сюда:

  • Про лень: В этом примере инициализация ленивая, то есть экземпляр создастся только когда ты впервые вызовешь DatabaseConnection(). Это хорошо, не грузим систему зря.
  • Не панацея: В больших Flutter-приложениях часто используют не голый синглтон, а пакеты для внедрения зависимостей — get_it, provider, riverpod. Это, блядь, как более цивилизованный способ иметь «единственный экземпляр», но в рамках определённой области. Тестировать такое — просто праздник по сравнению с классическим синглтоном, который прикипает к коду намертво.
  • Тестирование — его ахиллесова пята: Вот с этим глобальным состоянием потом в тестах голову можно сломать. Поэтому умные дяди советуют: если хочешь жить спокойно, используй интерфейсы и засовывай зависимости через конструктор. Так и тесты писать легче, и доверия к коду больше.

Короче, синглтон — инструмент мощный, но как топор. Можно дом построить, а можно себе по ноге дать. Используй с умом, а не просто потому что модно.