Назовите соображения дизайна при выборе между использованием одноэлементного или статического класса. При этом вы как бы вынуждены противопоставлять их, поэтому любые контрасты, которые вы можете придумать, также полезны для демонстрации вашего мыслительного процесса! Также каждый интервьюер любит видеть наглядные примеры. :)
design-patterns
cdleary
источник
источник
Ответы:
источник
Как насчет «избегать обоих»? Синглтоны и статические классы:
Вместо этого изучите библиотеки Injection Injection и Inversion of Control Container . Несколько библиотек IoC будут управлять жизненным циклом за вас.
(Как всегда, есть исключения, такие как статические математические классы и методы расширения C #.)
источник
Hide Dependencies
небольшая дополнительная информация по этому поводу: вы можете реализовать шаблон инверсии управления, например, с помощью Ninject . Это позволяет вам использовать только один экземпляр типа,SingletonScope
привязав его к a , что означает, что он всегда будет вводить один и тот же экземпляр, но класс не будет одноэлементным.Я бы сказал, что единственная разница заключается в синтаксисе: MySingleton.Current.Whatever () vs MySingleton.Whatever (). Состояние, как упомянул Дэвид, в конечном счете «статично» в любом случае.
РЕДАКТИРОВАТЬ: бригада захоронения пришла с digg ... во всяком случае, я подумал о случае, который потребует сингла. Статические классы не могут наследовать от базового класса или реализовывать интерфейс (по крайней мере, в .Net они не могут). Поэтому, если вам нужна эта функция, вы должны использовать синглтон.
источник
Одно из моих любимых обсуждений этой проблемы здесь (исходный сайт отключен, теперь связан с Internet Archive Wayback Machine ).
Подводя итог преимуществ гибкости синглтона:
источник
Статический класс с загрузкой статических переменных - это своего рода уловка.
Синглтон с реальным экземпляром лучше.
Состояние находится ТОЛЬКО в экземпляре.
Таким образом, синглтон можно изменить позже для создания пулов, локальных экземпляров потока и т. Д. И ни один из уже написанных кодов не нуждается в изменении, чтобы получить преимущество.
Можно сделать что-то подобное со статическим классом, но при косвенной отправке будут накладные расходы на вызовы.
Вы можете получить экземпляр и передать его функции в качестве аргумента. Это позволяет направить код на «правильный» синглтон. Мы знаем, что вам понадобится только одна из них ... пока вы этого не сделаете.
Большим преимуществом является то, что синглтоны с отслеживанием состояния можно сделать потокобезопасными, тогда как статический класс не может, если вы не измените его как секретный синглтон.
источник
Думайте о синглтоне как о службе. Это объект, который предоставляет определенный набор функций. Например
Фабрика объектов - это объект, который выполняет определенную услугу.
Напротив, класс, полный статических методов, представляет собой набор действий, которые вы можете захотеть выполнить, организованный в связанную группу (класс). Например
Пример StringUtils - это набор функций, которые можно применять где угодно. Одноэлементный фабричный объект - это особый тип объекта с четкой ответственностью, который может быть создан и передан при необходимости.
источник
Статические классы создаются во время выполнения. Это может занять много времени. Синглтоны могут быть созданы только при необходимости.
источник
Синглтоны не следует использовать так же, как статические классы. По сути,
по сути то же самое, что
На самом деле вам следует рассматривать синглтон как просто другой объект . Если службе требуется экземпляр одноэлементного типа, передайте этот экземпляр в конструктор:
Служба не должна знать, что объект является одноэлементным, и должна рассматривать объект как просто объект.
Объект, безусловно, может быть реализован как деталь реализации и как аспект общей конфигурации, как синглтон, если это упростит задачу. Но вещи, которые используют объект, не должны знать, является ли объект синглтоном или нет.
источник
Если под «статическим классом» вы подразумеваете класс, который имеет только статические переменные, то они действительно могут поддерживать состояние. Насколько я понимаю, единственная разница будет заключаться в способе доступа к этой вещи. Например:
против
Внутреннее устройство MySingleton, очевидно, будет различаться между ними, но, не говоря уже о проблемах безопасности потоков, они оба будут работать одинаково в отношении клиентского кода.
источник
Шаблон Singleton обычно используется для обслуживания независимых от экземпляра или статических данных, когда несколько потоков могут обращаться к данным одновременно. Одним из примеров могут быть коды штатов.
источник
Синглтоны никогда не должны использоваться (если вы не считаете класс без изменяемого состояния одиночным). "статические классы" не должны иметь изменяемого состояния, кроме, возможно, поточно-безопасных кешей и т.п.
Практически любой пример синглтона показывает, как этого не делать.
источник
Если синглтон - это то, от чего вы можете избавиться, чтобы очистить его после этого, вы можете рассматривать его, когда это ограниченный ресурс (т.е. только один из них), который вам не нужен все время, и у вас есть какая-то память или стоимость ресурса при его распределении.
Код очистки выглядит более естественно, когда у вас есть синглтон, в отличие от статического класса, содержащего поля статического состояния.
Однако код в любом случае будет выглядеть одинаково, поэтому, если у вас есть более конкретные причины для запроса, возможно, вам следует уточнить.
источник
Эти два могут быть очень похожими, но помните, что настоящий синглтон должен сам быть создан (предоставлен один раз), а затем обслуживаться. Класс базы данных PHP, который возвращает экземпляр, на
mysqli
самом деле не является синглтоном (как его называют некоторые люди), потому что он возвращает экземпляр другого класса, а не экземпляр класса, который имеет экземпляр как статический член.Итак, если вы пишете новый класс, который планируете разрешить только один экземпляр в своем коде, вы можете также написать его как синглтон. Подумайте об этом как о написании обычного класса и добавлении к нему, чтобы облегчить требование создания одного экземпляра. Если вы используете чужой класс, который не можете изменить (например,
mysqli
), вы должны использовать статический класс (даже если вы не можете указать префикс его определения с помощью ключевого слова).источник
Синглтоны более гибкие, что может быть полезно в тех случаях, когда вы хотите, чтобы метод Instance возвращал различные конкретные подклассы типа Singleton на основе некоторого контекста.
источник
Статические классы нельзя передавать как аргументы; экземпляры синглтона могут быть. Как упоминалось в других ответах, следите за проблемами потоковой передачи со статическими классами.
rp
источник
Синглтон может иметь конструктор и деструктор. В зависимости от вашего языка конструктор может вызываться автоматически при первом использовании синглтона или никогда, если ваш синглтон не используется вообще. Статический класс не будет иметь такой автоматической инициализации.
После получения ссылки на одноэлементный объект его можно использовать так же, как и любой другой объект. Клиентскому коду может даже не потребоваться знать, что он использует синглтон, если ссылка на синглтон хранится ранее:
Это, очевидно, упрощает задачу, когда вы решаете отказаться от шаблона Singleton в пользу реального шаблона, такого как IoC.
источник
Используйте шаблон singleton, когда вам нужно вычислить что-то во время выполнения, что вы бы вычислили во время компиляции, если бы вы могли, например таблицы поиска.
источник
Я думаю, что место, где Singleton будет иметь больше смысла, чем статический класс, - это когда вам нужно создать пул дорогостоящих ресурсов (например, соединений с базой данных). Вам не будет интересно создавать пул, если их никто никогда не использует (статический класс означает, что вы выполняете дорогостоящую работу, когда класс загружен).
источник
Синглтон также является хорошей идеей, если вы хотите принудительно кэшировать данные. например, у меня есть класс, который ищет определения в XML-документе. Поскольку синтаксический анализ документа может занять некоторое время, я установил кеш определений (я использую SoftReferences, чтобы избежать ошибок outOfmemeoryErrors). Если желаемого определения нет в кеше, я выполняю дорогостоящий синтаксический анализ xml. В противном случае возвращаю копию из кеша. Поскольку наличие нескольких кешей означало бы, что мне все равно придется загружать одно и то же определение несколько раз, мне нужен статический кеш. Я решил реализовать этот класс как одноэлемент, чтобы я мог писать класс, используя только обычные (нестатические) члены данных. Это позволяет мне по-прежнему создавать определение класса, если он мне понадобится по какой-либо причине (сериализация, модульное тестирование и т. Д.)
источник
Как уже упоминалось, синглтон похож на сервис. Плюс его гибкость. Статический, ну, вам нужны статические части для реализации синглтона.
В синглтоне есть код для создания экземпляра фактического объекта, который может оказаться большим подспорьем, если вы столкнетесь с проблемами гонок. В статическом решении вам может потребоваться решение гоночных задач в нескольких местах кода.
Однако так же, как синглтон может быть построен с некоторыми статическими переменными, вы можете сравнить его с goto. Это может быть очень полезно для создания других структур, но вам действительно нужно знать, как его использовать, и не следует «злоупотреблять» им. Поэтому общая рекомендация - придерживаться синглтона и при необходимости использовать static.
также проверьте другой пост: Почему стоит выбирать статический класс вместо одноэлементной реализации?
источник
сослаться на это
резюме:
а. Одно простое практическое правило, которому вы можете следовать, - если ему не нужно поддерживать состояние, вы можете использовать статический класс, в противном случае вы должны использовать синглтон.
б. используйте Singleton, если это особенно «тяжелый» объект. Если ваш объект большой и занимает разумный объем памяти, много n / w вызовов (пул соединений) и т. Д. Чтобы убедиться, что его экземпляр не будет создаваться несколько раз. Класс Singleton поможет предотвратить подобные ситуации.
источник
Когда одному классу нужно состояние. Синглтоны поддерживают глобальное состояние, а статические классы - нет.
Например, создание помощника для класса реестра: если у вас есть изменяемый куст (текущий пользователь HKey против локального компьютера HKEY), вы можете:
Теперь любые дальнейшие вызовы этого синглтона будут работать в кусте локальной машины. В противном случае, используя статический класс, вам нужно будет указать каждый куст локального компьютера или иметь такой метод, как
ReadSubkeyFromLocalMachine
.источник