Шаблон проектирования синглтона: подводные камни
В настоящее время я очень заинтересован в этом "шаблоне дизайна". Однако я не уверен, что при использовании этой строгой реализации глобального состояния есть недостатки. Итак, когда вы думаете, чтобы не практиковать синглтон в приложении?
4 ответа
Синглтон, как правило, плохая идея, если вы проводите модульное тестирование, и, как правило, плохая идея не проводить модульное тестирование (или BDD, или приемочное тестирование).
Придание объектам глобального состояния означает, что написанные вами модульные тесты с участием этих объектов будут изолированы и не будут связаны друг с другом. Вместо этого вам придется беспокоиться о сбросе состояния для каждого теста и поверьте мне... это никогда не делается в 100% случаев. Если вы не сбросите глобальное состояние, вы начнете становиться очень странным и трудным для отладки ошибок в ваших тестах, которые тратят время.
Глобальное состояние также увеличивает сцепление в вашем коде и делает его очень трудным для рефакторинга.
Идеальный метод - использовать контейнер IoC/DI (Spring, Guice и т. Д.) Для запроса объектов. Эти контейнеры часто имеют способы отображения объектов в виде "синглетонов", но у них также есть способы изменить это поведение в зависимости от ситуации (т. Е. Модульное тестирование и код вашего домена).
Конечно, все зависит от размера вашей проблемы. Если вы взламываете 4-классную испытательную установку, чтобы попробовать что-то, тогда используйте Singleton. Тем не менее, как только этот проект возродится и станет более масштабным и сложным, тогда начнется рефакторинг Singleton.
Google Tech Talks некоторое время назад провели хорошую презентацию о Global State и Singletons. Статический шаблон синглтона является злом, потому что вызывает нежелательные побочные эффекты и делает код непроверенным. Статический синглтон является ОО-версией глобальных переменных.
Решение состоит в том, чтобы просто создать один экземпляр объекта и передать его пользователям через внедрение зависимостей. DI-фреймворки, такие как Guice, упрощают определение хорошего вида синглетонов (в Guice просто аннотируйте класс с помощью @Singleton). Был похожий технический разговор под названием " Не смотри на вещи"! которые обсуждали DI больше.
Помимо проблем тестирования и проектирования, упомянутых в других статьях, существуют проблемы с Singletons и загрузчиками классов. Синглтоны на самом деле не являются "одиночными" для JVM или приложения - они достигают этого с помощью статического свойства, что на самом деле означает, что по одному на класс. Если имеется несколько загрузчиков классов - как на большинстве серверов приложений - каждое отдельное приложение получает новый загрузчик классов, даже в EJB используется несколько уровней загрузчиков классов. Экземпляр синглтона загружается на загрузчик классов - что в зависимости от того, что вы делаете с синглтоном, может не дать ожидаемых результатов.
Я бы использовал Синглтон очень редко. Из-за их природы (статические, глобальные объекты) их сложно использовать при модульном тестировании вашего кода. В конечном итоге вам нужно выполнить некоторую синхронизацию или встроить некоторые механизмы повторной инициализации, чтобы вы могли получить свежую версию для каждого модульного теста. Есть случаи, которые имеют смысл - скажем, например, класс глобальной конфигурации - но их гораздо меньше, чем, кажется, считают люди, не знакомые с синглтоном. Я знаю, что прошел фазу, когда я повсюду видел применение шаблона синглтона. Теперь я избегаю его везде, где только могу, и отменяю его с помощью рефакторинга в моем коде, когда сталкиваюсь с ненужной реализацией.