Singleton (Одиночка) — это такой паттерн кода, когда в программе есть только один-единственный экземпляр некоего объекта. У разных языков есть разные средства для реализации этого паттерна, например в питоне каждый модуль вместе с его свойствами и есть такой объект, к которому может обратиться любая часть программы просто по его имени. И это плохо!

Кажется, что с синглтонами жить легко и просто, и они избавляют от множества забот, вроде передачи конфигурации и требуемых зависимостей. Кажется, что они повышают инкапсуляцию, потому что в вызовы приходится передавать меньше параметров. Но на самом деле то всего лишь иллюзия. И она рассеивается, когда вы начинаете писать юнит-тесты. Объект использует базу данных, доступную из глобальной переменной? Потрудитесь перед этим подключиться к ней, или создать необходимые mock’и и тоже воткнуть их в глобальную переменную. Не забудьте, что после теста придется возвращать эту фигню на место, откатывая изменения или пересоздавая mock’и. Тесты становятся уродливыми, непонятными костылями. Бывает даже при добавлении еще одного теста (не кода, а теста!) перестают проходить старые тесты совсем другой части программы. Синглтоны нарушают изоляцию частей программы друг от друга и делают поведение нестабильным.

Избежать проблем можно двумя другими паттернами: Service Locator и Dependency Inversion/Injection.

Первый заменяет синглтон на другой синглтон, который не хранит состояние, но зато может найти того, кто это состояние имеет. Это может упростить тестирование, но на самом деле все тот же одиночка с теми же проблемами. Вам придется данные (или реализацию), которые хранил синглтон, как-то регистрировать в локаторе.

Dependency Inversion — это совершенно другой подход, когда необходимые данные и реализации передаются в параметрах к вызываемому коду. Способ передачи не важен — в конструктор ли, в отдельный метод или вообще прямая запись в атрибут. Главное то, что синглтон становится неявным: о том, то он в системе только один, заботится вызывающая процедура, которая сама создаст (или получит) требуемый объект. Такой подход не только отвязывает код от одиночки, но и значительно увеличивает инкапсуляцию: вызываемый код не зависит ни от чего, даже от локатора. Кроме того, зависимости становятся явными, что означает гораздо меньше сюрпризов при рефакторинге.

На пикрелейтеде — не просто рандомный чувак, а продюсер, режиссер и сценарист Джон Синглтон. А какую картинку вы ожидали в технической статье об абстракциях в коде?