Наиболее распространенные примеры неправильного использования одноэлементного класса

StackOverflow https://stackoverflow.com/questions/135347

Вопрос

Когда НЕ следует использовать одноэлементный класс, хотя это может быть очень заманчиво?Было бы очень хорошо, если бы у нас был список наиболее распространенных случаев «синглтонита», которых нам следует избегать.

Это было полезно?

Решение

Не используйте синглтон для чего-то, что может превратиться в мультиплицируемый ресурс.

Вероятно, это звучит глупо, но если вы объявляете что-то синглтоном, вы делаете очень сильное заявление о том, что оно абсолютно уникально.Вы строите код вокруг этого, все больше и больше.И когда после тысяч строк кода вы обнаруживаете, что это вообще не синглтон, перед вами стоит огромный объем работы, потому что все остальные объекты ожидают, что «священный» объект класса WizBang будет синглтоном. .

Типичный пример:«Существует только одно подключение к базе данных, которое имеет это приложение, таким образом, это синглтон». - Плохая идея.Возможно, в будущем вам захочется иметь несколько связей.Лучше создать пул подключений к базе данных и заполнить его только одним экземпляром.Действует как синглтон, но весь остальной код будет иметь расширяемый код для доступа к пулу.

РЕДАКТИРОВАТЬ: Я понимаю, что теоретически синглтон можно расширить на несколько объектов.Однако реального жизненного цикла (например, объединения/извлечения из пула) не существует, а это означает, что нет реального владения переданными объектами, т.е.теперь мульти-синглтон должен быть без сохранения состояния, чтобы его можно было использовать одновременно разными методами и потоками.

Другие советы

Ну, синглтоны по большей части просто делают вещи статичными.Таким образом, вы либо фактически делаете данные глобальными, а мы все знаем, что глобальные переменные — это плохо, либо вы пишете статические методы, и это уже не очень ОО, не так ли?

Здесь — это более подробная разглагольствования Стива Йегге о том, почему синглтоны плохи.По сути, вам не следует использовать синглтоны почти во всех случаях, вы не можете быть уверены, что они никогда не понадобятся более чем в одном месте.

Я знаю, что многие ответили: «Когда у вас их больше одного» и т. д.

Поскольку в исходном постере был приведен список случаев, когда вам не следует использовать синглтоны (а не основная причина), я подключаюсь:

Всякий раз, когда вы его используете, потому что вам не разрешено использовать глобальное значение!

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

Несколько лет назад я совершил большое преступление (к счастью, с тех пор я усвоил урок).

Произошло следующее: я взялся за проект настольного приложения, который был преобразован в .Net из VB6, и это был настоящий беспорядок.Такие вещи, как 40-страничные (печатные) функции и отсутствие реальной структуры классов.Я создал класс для инкапсуляции доступа к базе данных.Это не реальный уровень данных (пока), а просто базовый класс, который может использовать реальный уровень данных.Где-то мне пришла в голову блестящая идея сделать этот класс одноэлементным.Примерно год все работало нормально, а затем нам понадобилось создать веб-интерфейс для приложения.Синглтон оказался огромным узким местом для базы данных, поскольку всем веб-пользователям приходилось использовать одно и то же соединение.Снова...урок выучен.

Оглядываясь назад, можно сказать, что на какое-то время это, вероятно, было правильным выбором, поскольку заставило других разработчиков быть более дисциплинированными в его использовании и заставило их осознать проблемы масштабирования, которые ранее не были проблемой в мире VB6.Но мне следовало вернуть его обратно через несколько недель, прежде чем вокруг него накопилось слишком много вещей.

Вот это напыщенная речь мой друг Алекс Миллер...В нем нет точного перечисления «когда НЕ следует использовать синглтон», но это всеобъемлющий, отличный пост, в котором утверждается, что синглтон следует использовать только в редких случаях, если вообще следует использовать.

Синглтоны практически всегда являются плохой идеей и, как правило, бесполезными/избыточными, поскольку они представляют собой лишь очень ограниченное упрощение достойного шаблона.

Посмотрите, как работает внедрение зависимостей.Он решает те же проблемы, но гораздо более полезным способом — на самом деле вы обнаружите, что это применимо ко многим другим частям вашего дизайна.

Хотя вы можете найти библиотеки DI, вы также можете создать базовую библиотеку самостоятельно, это довольно легко.

Я стараюсь иметь только один синглтон - инверсию объекта локатора управления/сервиса.

IService service = IoC.GetImplementationOf<IService>();

Одна из вещей, которая делает это кошмаром, — это то, что оно содержит модифицируемый глобальное государство.Я работал над проектом, в котором синглтоны использовались повсюду для задач, которые нужно было решать совершенно другим способом (передавать стратегии и т. д.). «Десинглтонификация» в некоторых случаях представляла собой серьезное переписывание частей система.Я бы сказал, что в большинстве случаев, когда люди используют синглтон, это просто неправильно, потому что сначала он выглядит красиво, но превращается в проблему, особенно при тестировании.

Если у вас есть несколько приложений, работающих в одной JVM.

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

Иногда вы предполагаете, что будет только одна вещь, но потом оказываетесь неправы.

Пример, класс базы данных.Вы предполагаете, что будете подключаться только к базе данных вашего приложения.

// Its our database! We'll never need another
class Database
{
};

Но ждать!Твой начальник говорит, подключись к базе данных других ребят.Допустим, вы хотите добавить phpbb на сайт и хотели бы воспользоваться его базой данных, чтобы интегрировать некоторые его функции.Должны ли мы создать новый синглтон или другой экземпляр базы данных?Большинство людей сходятся во мнении, что предпочтительнее новый экземпляр того же класса, дублирования кода нет.

Вы бы предпочли иметь

Database ourDb;
Database otherDb;

чем скопировать базу данных и сделать:

// Copy-pasted from our home-grown database.
class OtherGuysDatabase
{
};

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

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

Но почему бы тебе не доступ все ваши соединения через один интерфейс (т.е.диспетчер соединений)?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top