Должен ли я беспокоиться об использовании одноэлементных классов? [Дубликат]

Я предполагаю, что ошибка возникает в этой строке:

con.Open(); // InvalidOperationException if it's already open

, поскольку вы повторно используете соединение, и вы, вероятно, не закрыли его в последний раз.

всегда закрывайте соединение сразу, как только вы закончите с ним, лучше всего используйте using-statement:

public void run_runcommand(string query)   
{
    using(var con = new SqlConnection(connectionString))
    using(var cmd = new SqlCommand(query, con))
    {
        con.Open();
        // ...
    }  // close not needed since dispose also closes the connection
}

. Обратите внимание, что вы не должны использовать блок Catch только для повторного исключения исключения. Если вы ничего не делаете с этим, не поймайте его вообще. Было бы еще лучше использовать throw; вместо throw ex;, чтобы сохранить трассировку стека. https://stackoverflow.com/a/4761295/284240

1740
задан 9 revs, 7 users 29% 27 July 2017 в 09:09
поделиться

25 ответов

Парафраз из Брайана Баттона:

  1. Они обычно используются в качестве глобального экземпляра, почему это так плохо? Потому что вы скрываете зависимости вашего приложения в своем коде, вместо того, чтобы разоблачать их через интерфейсы. Сделать что-то глобальное, чтобы избежать его прохождения, это запах кода .
  2. Они нарушают принцип единой ответственности : в силу того, что они контролируют свои собственное создание и жизненный цикл.
  3. Они по сути заставляют код плотно соединены . Это во многих случаях затрудняет их подтасовку.
  4. Они несут состояние в течение всего срока службы приложения. Еще один удар по тестированию, так как вы можете закончить ситуацию, когда нужно заказать тесты, что не является большим для нетипичных тестов. Зачем? Поскольку каждый модульный тест должен быть независимым от другого.
1150
ответ дан 4 revs, 4 users 65% 16 August 2018 в 02:05
поделиться
  • 1
    Я не согласен с вами. Поскольку комментарии разрешены только 600 символов, я написал сообщение в блоге, чтобы прокомментировать это, пожалуйста, см. Ссылку ниже. jorudolph.wordpress.com/2009/11/22/singleton-considerations – Johannes Rudolph 22 November 2009 в 15:35
  • 2
    В пунктах 1 и 4 я считаю, что однопользовательские приложения полезны и на самом деле почти идеальны для кэширования данных (особенно из БД). Увеличение производительности намного превосходит сложности, связанные с модульными модульными тестами. – Dai Bok 2 December 2009 в 16:46
  • 3
    @Dai Bok: "данные кэширования (особенно из БД)" используйте прокси-шаблон для этого ... – paxos1977 14 January 2010 в 00:08
  • 4
    Ничего себе, отличные ответы. Я, вероятно, использовал здесь чрезмерно агрессивные формулировки, поэтому, пожалуйста, имейте в виду, что я отвечал на вопрос с отрицательным результатом. Мой ответ должен был быть кратким списком «анти-шаблонов», которые возникают из-за плохого использования Singleton. Полное раскрытие; Я тоже время от времени использую Singletons. Есть более нейтрально поставленные вопросы о SO, которые сделают отличные форумы, когда Singletons можно считать хорошей идеей. Например, stackoverflow.com/questions/228164/… – Jim Burger 16 April 2010 в 07:23
  • 5
    Они не так хороши для кэширования в многопоточной среде. Вы можете легко победить кеш с несколькими потоками, борющимися за ограниченный ресурс. [поддерживается одним движением] – monksy 28 March 2011 в 15:56

Синглтон не о единичном экземпляре!

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

  • Проблема: Singleton может быть проблемой в многопотоковой среде. Решение. Используйте однопоточный процесс начальной загрузки для инициализации всех зависимостей вашего синглтона.
  • Проблема. Трудно издеваться одиночки. Решение: используйте метод Factory для издевательства MyModel myModel = Factory.inject(MyModel.class); . Вы можете сопоставить MyModel с TestMyModel классом, который наследует его, везде, где MyModel будет введен, вы получите TestMyModel instread.
  • Проблема: синглтоны могут вызывать лук-поры, которые они никогда не выбрали. Решение: Ну, распоряжайтесь им! Внедрите обратный вызов в своем приложении, чтобы правильно разместить одиночные пакеты, вы должны удалить любые связанные с ними данные и, наконец: удалить их с Factory.

Как я сказал в названии singleton, речь идет не о одном экземпляре.

  • Синглтоны улучшают читаемость: вы можете посмотреть на свой класс и посмотреть, какой синглтон он ввел чтобы выяснить, что это за зависимости.
  • Синглтоны улучшают обслуживание: как только вы удалили зависимость от класса, вы просто удалили одну инъекцию синглтона, вам не нужно идти и редактировать большую ссылку других классов, которые просто изменил вашу зависимость (это вонючий код для меня @Jim Burger )
  • Синглоты улучшают память и производительность: когда что-то происходит в вашем приложении, и требуется длинная цепочка обратных вызовов для доставки, вы теряете память и производительность, используя Singleton, вы сокращаете среднего человека и улучшаете производительность и использование памяти (избегая ненужных локальных переменных).
21
ответ дан 2 revs 16 August 2018 в 02:05
поделиться
  • 1
    Это не касается моей основной проблемы с Singletons, которая позволяет разрешать доступ к глобальному состоянию из любого из тысяч классов в вашем проекте. – LegendLength 6 January 2016 в 03:39
  • 2
    Это было бы целью ... – Ilya Gazman 6 January 2016 в 06:19

Слишком много людей помещают объекты, которые не являются потокобезопасными в одноэлементном шаблоне. Я видел примеры DataContext ( LINQ & nbsp; to SQL-файл ), выполненный в одноэлементном шаблоне, несмотря на то, что DataContext не является потокобезопасным и является чисто единичным объектом.

104
ответ дан 2 revs, 2 users 67% 16 August 2018 в 02:05
поделиться
  • 1
    не являются ли весенние бобы, по умолчанию, Singletons? – slim 8 February 2010 в 16:50
  • 2
    Да, но я имею в виду «кодирование» синглетов. Я не написал «singleton» (т. Е. С частным конструктором yada yada yada в соответствии с шаблоном проектирования), но да, с весной я использую один экземпляр. – prule 16 February 2010 в 20:59
  • 3
    Что это за один экземпляр, доступный во всем приложении? Ой. <Я> Global . «Синглтон» является , а не шаблоном для обертывания глобальных символов ». является либо наивным, либо вводящим в заблуждение, поскольку по определению , шаблон обертывает класс вокруг глобального экземпляра. – cHao 19 February 2013 в 09:10
  • 4
    Мой опыт в том, что запуск с синглонами действительно повредит вам даже в краткосрочной перспективе, не считая длительный пробег. Этот эффект может быть мне меньше, если приложение уже существует в течение некоторого времени и, вероятно, уже заражено другими синглетонами. Начиная с нуля? Избегайте их любой ценой! Хотите один экземпляр объекта? Позвольте фабрике управлять созданием этого объекта. – Sven 17 May 2013 в 20:36
  • 5
    AFAIK Singleton является заводским методом. Таким образом, я не получаю вашу рекомендацию. – tacone 17 May 2013 в 23:37
  • 6
    "Завод" ! = "Factory_method, который не может быть отделен от другого полезного материала в том же классе" – Sven 18 May 2013 в 01:12
  • 7
    Это скорее похоже на проблему с модульным тестированием, которое может тестировать объекты (единицы), функции (единицы), целые библиотеки (единицы), но не с чем-либо статическим в классе (также единицами). – v010dya 3 February 2014 в 06:35
  • 8
    Конечно, вы можете создавать один экземпляр класса при запуске приложения и вводить этот экземпляр через интерфейс во все, что его использует. Реализация не должна волновать, что может быть только один. – Scott Whitlock 31 March 2014 в 20:33
  • 9
    вы не думаете, все равно, чтобы все внешние ссылки? Если да, то какая проблема для moc singleton, если нет, действительно ли вы выполняете модульное тестирование? – Dainius 24 October 2014 в 12:28
  • 10
    поэтому, когда другие это делают, это нормально (если я буду использовать это после), но если другие это сделают, и я не буду использовать его, это зло? – Dainius 24 October 2014 в 12:32
  • 11
    многие люди пишут небезопасный многопоточный код, значит ли это, что мы должны устранять потоки? – Dainius 24 October 2014 в 12:35
  • 12
    @Dainius: В конце концов, на самом деле нет. Конечно, вы не можете произвольно заменить экземпляр на другой. (За исключением тех моментов, вызывающих facepalm, когда вы делаете . Я уже видел методы setInstance раньше.) Это вряд ли имеет значение, однако, - что weenie, который «нужен», синглтон также не знал ничего необычного в инкапсуляции или что не так с изменчивым глобальным состоянием, поэтому он с благодарностью (?) предоставлял сеттеры для каждого. Один. поле. (И да, это происходит. lot . Почти каждый синглтон, который я когда-либо видел в дикой природе, был изменчив по дизайну и часто смущающе.) – cHao 8 January 2015 в 06:42
  • 13
    @Dainius: На самом деле, да. IMO модель параллелизма по умолчанию должна быть многопроцессорной, с возможностью для двух процессов (1) легко передавать сообщения друг другу и / или (2) обмениваться памятью по мере необходимости. Threading полезен, если вы хотите разделить все , но вы этого действительно не хотите. Его можно эмулировать путем совместного использования всего адресного пространства, но это также будет считаться анти-шаблоном. – cHao 9 January 2015 в 19:20
  • 14
    @Dainius: И, конечно, это предполагает, что параллелизм честности и доброты необходим вообще. Часто все, что вы хотите, это иметь возможность сделать одно, пока вы ждете, пока ОС сделает что-то еще. (Например, обновление пользовательского интерфейса при чтении из сокета.) Приличный API-интерфейс async может в полной мере избавиться от ненужных потоков в огромном большинстве случаев. – cHao 9 January 2015 в 19:50
  • 15
    поэтому, если у вас огромная матрица данных, вам нужен процесс, лучше сделать это в одном потоке, потому что многие люди могут это сделать неправильно. – Dainius 10 January 2015 в 20:19
  • 16
    @Dainius: В значительной степени у нас уже есть. «Предпочтительная композиция по наследованию» это уже давно. Если наследование является лучшим решением, вы, конечно, можете его использовать. То же самое происходит с синглонами, глобалями, потоками, goto и т. Д. Во многих случаях они могут работать , но, откровенно говоря, «работает». недостаточно - если вы хотите идти против общепринятой мудрости, вам лучше продемонстрировать, как ваш подход лучше , чем обычные решения. И я еще не видел такого случая для шаблона Singleton. – cHao 11 January 2015 в 00:20
  • 17
    @Dainius: Во многих случаях да. (Threading может фактически замедлить вас , если вы добавите синхронизацию в микс. Это яркий пример того, почему многопоточность не должна быть первой мыслью большинства людей.) В других случаях было бы лучше чтобы иметь два процесса, которые разделяют только необходимые вещи. Конечно, вам нужно будет организовать процессы для обмена памятью. Но, честно говоря, я вижу это как вещь good - намного лучше, чем по умолчанию, для дефолта в режиме общего доступа. Это требует, чтобы вы прямо заявляли (и, в идеале, знать), какие части разделяют, и, следовательно, какие части должны быть потокобезопасными. – cHao 11 January 2015 в 00:49
  • 18
    @Dainius: Mocking экземпляры намного меньше проблем, чем насмешливые классы. Вы могли бы, вероятно, извлечь тестируемый класс из остальной части приложения и протестировать поддельный класс Singleton. Однако это очень усложняет процесс тестирования. Например, теперь вам нужно иметь возможность разгружать классы по своему усмотрению (на самом деле это не вариант на большинстве языков) или запускать новую виртуальную машину для каждого теста (чтение: тесты могут занимать тысячи раз). Для двоих, однако, зависимость от Singleton - это деталь реализации, которая теперь протекает по всем вашим тестам. – cHao 11 January 2015 в 04:07
  • 19
    Чтобы мы не разговаривали друг с другом, я говорю не только о глобально доступном экземпляре. Для этого есть много случаев. То, о чем я говорю (особенно, когда я говорю «capital-S Singleton»), является шаблоном Singleton GoF, который вставляет этот единственный глобальный экземпляр в сам класс, предоставляет его с помощью метода getInstance или аналогичного имени и предотвращает существование второго экземпляра. Честно говоря, в этот момент вы могли бы даже не иметь экземпляр one . – cHao 12 January 2015 в 13:30
  • 20
    Powermock может издеваться над статическим материалом. – Snicolas 28 May 2015 в 04:50
  • 21
    делает издевательство над объектом, создавая реальный объект? Если издевательство не создает реального объекта, то почему имеет значение, является ли класс singleton или метод статическим? – Arun Raaj 13 August 2018 в 11:12

Недавняя статья по этому вопросу Криса Рита в Кодирование без комментариев .

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

http://geekswithblogs.net/AngelEyes/archive/2013/09/08/singleton-i-love-you- но-Youre приносящие меня вниз-ре-uploaded.aspx

7
ответ дан 2 revs, 2 users 75% 16 August 2018 в 02:05
поделиться

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

Использование одного экземпляра класса является допустимой конструкцией как если вы применяете в коде следующие средства:

  1. Убедитесь, что класс, который будет использоваться как одноэлементный, реализует интерфейс. Это позволяет реализовать заглушки или макеты с использованием того же интерфейса
  2. Убедитесь, что Singleton является потокобезопасным. Это заданное.
  3. Синглтон должен быть простым по своей природе и не слишком сложным.
  4. Во время выполнения вашего приложения, где нужно передать одноточие в данный объект, используйте класса, который создает этот объект и имеет фабрику классов, передающую экземпляр singleton классу, который ему нужен.
  5. Во время тестирования и обеспечения детерминированного поведения создайте одиночный экземпляр как отдельный экземпляр как сам фактический класс или stub / mock, который реализует свое поведение и передает его, как и классу, который этого требует. Не используйте фактор класса, который создает этот объект под тестом, который нуждается в синглтоне во время теста, поскольку он пройдет один глобальный экземпляр, который побеждает цель.

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

16
ответ дан 2 revs, 2 users 92%user1578119 16 August 2018 в 02:05
поделиться
  • 1
    +1, Наконец ответ, который обращается к , когда может быть синглтон. – Pacerier 25 June 2014 в 02:30

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

Два самых больших винта, которые я вижу: рассматривают его как глобальный & amp; неспособный определить замыкание Синглтона.

Все говорят о Синглтоне как о глобалах, потому что они в основном. Тем не менее, много (к сожалению, не все) плохости в глобальном мире не по своей природе не является глобальным, а тем, как вы его используете. То же самое касается Singletons. На самом деле больше, так как «единый экземпляр» действительно не означает «глобально доступный». Это скорее естественный побочный продукт, и, учитывая все плохое, что мы знаем, приходит из него, мы не должны так торопиться, чтобы использовать глобальную доступность. Когда программисты видят Singleton, они, похоже, всегда получают доступ к нему напрямую через свой метод экземпляра. Вместо этого вы должны перейти к нему так же, как и любой другой объект. Большинство кодов не должны даже знать, что он имеет дело с синглтоном (свободная связь, правда?). Если только маленький бит кода обращается к объекту, подобному глобальному, большой вред отменяется. Я рекомендую использовать его, ограничивая доступ к функции экземпляра.

Синтаксический контекст также очень важен. Определяющая характеристика Singleton заключается в том, что существует «только одна», но, по правде говоря, она «только одна» в каком-то контексте / пространстве имен. Они обычно являются одним из: по одному на поток, процесс, IP-адрес или кластер, но также могут быть по одному на процессор, машину, пространство имен языков / загрузчик классов / независимо, подсеть, Интернет и т. Д.

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

Если вы избегаете этих ошибок, Singletons все еще может быть PITA, бит готов увидеть много худших проблем, которые значительно смягчены. Представьте себе сингл Java, то есть явно определяемый как один раз для загрузчика классов (что означает, что ему нужна политика безопасности потоков), с определенными методами создания и уничтожения и жизненным циклом, который диктует, когда и как они вызваны, и чей «экземплярный» метод имеет защиту пакета, поэтому к нему обычно обращаются через другие, неглобальные объекты. Все еще потенциальный источник проблем, но, безусловно, гораздо меньше проблем.

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

20
ответ дан 2 revs, 2 users 96% 16 August 2018 в 02:05
поделиться

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

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

11
ответ дан 3 revs, 2 users 79% 16 August 2018 в 02:05
поделиться
  • 1
    Спасибо Loki :) Точно моя точка. Вся охота на ведьм напоминает мне о дебатах. Инструменты предназначены для людей, которые знают, как их использовать; использование инструмента, который вам не нравится, может быть опасным для вас, поэтому избегайте его, но НЕ говорите другим, чтобы они не использовали / не научились правильно его использовать. Я не совсем «про-синглтон». но мне нравится тот факт, что у меня есть такой инструмент, и я чувствую, где это целесообразно использовать. Период. – dkellner 29 December 2015 в 17:58

Некоторые кодирующие снобы смотрят на них как на простое прославленное глобальное. Точно так же, как многие люди ненавидят инструкцию goto , есть другие, которые ненавидят идею когда-либо использовать глобальный . Я видел, как несколько разработчиков идут на необычные длины, чтобы избежать global , потому что они считали использование одного в качестве допуска отказа. Странно, но верно.

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

308
ответ дан 3 revs, 2 users 83% 16 August 2018 в 02:05
поделиться
  • 1
    Ошибка, которую я вижу в Синглтоне, заключается в том, что люди используют их вместо глобальных, потому что они как-то «лучше». Проблема (как я вижу), что вещи, которые Синглтон приносит в таблицу в этих случаях, не имеют значения. (Конструкция на первом использовании тривиальна для реализации в не-singleton, например, даже если на самом деле она не использует конструктор для этого). – dash-tom-bang 7 April 2010 в 20:10
  • 2
    Причина & quot; мы & quot; взглянуть на них, так это то, что «мы» очень часто их считают неправильными, и слишком часто. & Quot; Мы & Quot; знайте, что у них есть свое место. – Bjarke Freund-Hansen 10 February 2012 в 12:59
  • 3
    @Phil, вы заявили, «время от времени вы можете найти, что это идеальное решение, и поэтому используйте его». Хорошо, так точно в , который мог бы найти одноэлементный полезный? – Pacerier 25 June 2014 в 02:37
  • 4
    @Pacerier, когда выполняются все следующие условия: (1) вам нужно только одно: (2) вам нужно передать эту вещь в качестве аргумента при большом количестве вызовов методов, (3) вы готовы принять вероятность того, что когда-нибудь понадобится рефакторинг в обмен на немедленное сокращение размера и сложности вашего кода, не передавая всю проклятую вещь повсюду. – antinome 17 September 2014 в 19:37
  • 5
    Я не чувствую, что это что-то отвечает, он просто говорит, что «иногда это может поместиться, иногда это может быть не так». Хорошо, но почему, и когда? Что делает этот ответ более чем аргументом для модерации ? – Guildenstern 24 October 2014 в 19:59

См. Википедия Singleton_pattern

. Некоторые считают, что это анти-шаблон, который считает, что он чрезмерно используется, вводя ненужные ограничения в ситуациях, когда единственный экземпляр класса на самом деле не требуется. [1] [2] [3] [4]

Ссылки (только соответствующие ссылки из статьи)

  1. ^ Алекс Миллер. Я ненавижу # 1: Singleton , июль 2007 г.
  2. ^ Скотт Денсмор. Почему синглетоны злы , май 2004 г.
  3. ^ Стив Йегге. Синглтоны считаются глупыми , сентябрь 2004 г.
  4. ^ J.B. Rainsberger, IBM. Используйте свои синглтоны разумно , июль 2001 г.
20
ответ дан 3 revs, 2 users 86% 16 August 2018 в 02:05
поделиться
  • 1
    Описание о шаблоне не объясняет, почему оно считается злым ... – Jrgns 26 September 2008 в 10:31
  • 2
    Вряд ли справедливо: «Некоторые считают, что некоторые люди, которые считают, что они чрезмерно используются, вводят ненужные ограничения в ситуациях, когда на самом деле не требуется единственный экземпляр класса. & Quot; Посмотрите на ссылки ... Во всяком случае, для меня RTFM. – GUI Junkie 26 September 2008 в 11:58

Синглеты решают одну (и только одну) проблему.

Конфликт ресурсов.

Если у вас есть ресурс, который

(1) может иметь только единственный экземпляр и

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

вам нужен синглтон.

Существует не так много примеров. Файл журнала является большим. Вы не хотите просто отказаться от одного файла журнала. Вы хотите сбросить, синхронизировать и закрыть его должным образом. Это пример одного общего ресурса, который нужно управлять.

Редко, что вам нужен синглтон. Причина, по которой они плохи, заключается в том, что они чувствуют себя как global , и они являются полностью оплаченным членом книги GoF Design Patterns .

Когда вы думаете, что вам нужен глобальный, вы, вероятно, ошиблись в дизайне.

401
ответ дан 3 revs, 3 users 57% 16 August 2018 в 02:05
поделиться
  • 1
    Оборудование также является примером? Встраиваемые системы имеют множество аппаратных средств, которые могут использовать синглтоны - или, может быть, один большой? & Lt; & Гринь GT; – Jeff 28 April 2009 в 01:29
  • 2
    Полностью согласен. Существует много определенных «эта практика плохая». разговоры, плавающие вокруг, без какого-либо признания того, что практика может иметь свое место. Часто практика является только «плохой». потому что это часто неправильно используется. В шаблоне Singleton нет ничего неправильного, если он применяется соответствующим образом. – Damovisa 28 April 2009 в 01:34
  • 3
    Реальные, по принципу синглтоны очень редки (и очередь принтера, конечно, не одна, и ни один файл журнала - см. Log4j). Чаще всего аппаратное обеспечение является одноточечным по совпадению, а не по принципу. Все аппаратное обеспечение, подключенное к ПК, в лучшем случае является совпадающим одинарным (думаю, несколько мониторов, мышей, принтеров, звуковых карт). Даже 500-миллионный детектор частиц представляет собой однотонный случай совпадения и бюджетные ограничения, которые не применяются в программном обеспечении, таким образом: нет singleton. В телекоммуникациях ни номер телефона, ни физический телефон не являются одиночными (думаю, ISDN, колл-центр). – digitalarbeiter 7 April 2010 в 15:04
  • 4
    Аппаратное обеспечение может иметь только один экземпляр различных ресурсов, но аппаратное обеспечение не является программным обеспечением. Нет никакой причины, что один последовательный порт на доске разработки должен быть смоделирован как Singleton. Действительно, при моделировании это только затруднит перенос на новую плату с двумя портами! – dash-tom-bang 7 April 2010 в 20:02
  • 5
    Таким образом, вы должны писать два одинаковых класса, дублируя много кода, чтобы вы могли иметь два синглтона, представляющих два порта? Как просто использовать два глобальных объекта SerialPort? Как насчет того, чтобы не моделировать оборудование как классы вообще? И почему вы используете одиночные игры, что также подразумевает глобальный доступ? Вы хотите, чтобы каждая функция в вашем коде имела доступ к последовательному порту? – jalf 25 June 2010 в 03:31

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

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

Итак, в основном:

public MyConstructor(Singleton singleton) {
    this.singleton = singleton;
}

, а не:

public MyConstructor() {
    this.singleton = Singleton.getInstance();
}

Я считаю, что этот тип шаблона называется инъекции зависимостей и обычно считается хорошей.

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

71
ответ дан 3 revs, 3 users 73% 16 August 2018 в 02:05
поделиться
  • 1
    Хех, если вы сделаете это повсюду, тогда вам также придется перебирать ссылку на singelton повсюду, и, таким образом, у вас больше нет сингла. :) (Обычно это хорошо, ИМО.) – Bjarke Freund-Hansen 10 February 2012 в 13:02
  • 2
    @ BjarkeFreund-Hansen - чепуха, о чем вы говорите? Синглтон - это просто экземпляр класса, который устанавливается один раз. Ссылка на такой Синглтон не копирует фактический объект, он просто ссылается на него - у вас все еще есть тот же объект (читай: Singleton). – M. Mimpen 11 December 2013 в 12:35
  • 3
    @ M.Mimpen: Нет, капитал-синглтон (который здесь обсуждается) является экземпляром класса, который (a) гарантирует , что только один экземпляр когда-либо будет существовать, и (b ) осуществляется через встроенную глобальную точку доступа класса. Если вы заявили, что ничего не следует вызывать getInstance(), то (b) не совсем верно. – cHao 17 February 2014 в 16:50
  • 4
    @cHao Я не следую за вами или вы не понимаете, кому я комментирую - что касается Бьярке Фрейнда-Хансена. Бьярк утверждает, что наличие нескольких ссылок на одноэлементный результат имеет несколько синглетонов. Это, конечно, не так, поскольку нет глубоких копий. – M. Mimpen 17 February 2014 в 20:15
  • 5
    @ M.Mimpen: Я беру его комментарий, чтобы больше коснуться семантического эффекта. После того, как вы анонсировали вызовы на getInstance(), вы эффективно выбрасывали одно полезное различие между шаблоном Singleton и обычной ссылкой. Что касается остальной части кода, то одиночество больше не является свойством. Только вызывающему абоненту getInstance() когда-либо нужно знать или даже заботиться о том, сколько экземпляров существует. При использовании только одного вызывающего абонента, он требует больше усилий и гибкости для того, чтобы класс надежно обеспечивал единство, чем это делает, чтобы вызывающий абонент просто хранил ссылку и повторно использовал ее. – cHao 17 February 2014 в 20:52

Misko Hevery, из Google, содержит некоторые интересные статьи именно по этой теме ...

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

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

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

200
ответ дан 4 revs, 2 users 82% 16 August 2018 в 02:05
поделиться
  • 1
    В настоящее время статьи Мишко об этом лучше всего подходят. – Chris Mayer 26 September 2008 в 07:34
  • 2
    Первая ссылка фактически не затрагивает проблему с одиночными точками, а скорее предполагает статическую зависимость внутри класса. Исправить данный пример можно, передав параметры, но все же используйте синглтоны. – DGM 15 October 2008 в 14:57
  • 3
    @DGM: Точно - на самом деле существует огромное логическое разъединение между частью «обоснования» статьи и частью «Синглтоны являются причиной». – Harper Shelby 29 December 2008 в 21:56
  • 4
    Статья CreditCard от Misko является экстремальным примером неправильного использования этого шаблона. – Alex 25 April 2012 в 14:17
  • 5
    Чтение второй статьи Синглтоны на самом деле являются частью описанной объектной модели. Однако, вместо того, чтобы быть доступными глобально, они являются частными для объектов Factory. – FruitBreak 30 October 2012 в 18:41

Монополия - это дьявол, а синглтоны с не-readonly / изменяемым состоянием являются «реальной» проблемой ...

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

Глобально плохо, потому что:

  • а. Это вызывает конфликт пространства имен
  • b. Он обнародует состояние необоснованным образом

. Когда дело доходит до синглтонов

  • a. Явный способ OO их вызова, предотвращает конфликты, поэтому укажите a. не является проблемой
  • b. Синглтоны без состояния (например, фабрики) не являются проблемой. Синглтоны с состоянием могут снова попадать в две категории: те, которые неизменяемы или пишут один раз и читают много (файлы конфигурации / свойства). Это неплохо.

В последнем заявлении он ссылается на концепцию блога о том, что «одиночки являются лжецами».

Как это относится к монополии?

Чтобы начать игру монополии, сначала:

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

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

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

Теперь игра идет от дружественных кубиков к серьезному бизнесу. Боб был приведен в пример неудачи, и Джо и Эд не хотят заканчивать так, как «тот парень». Итак, будучи ведущим игроком, вы внезапно становитесь врагом. Джо и Эд начинают практиковать торговлю под столом, прямую инъекцию денег, недооцененную домашнюю замену и вообще что-нибудь, чтобы ослабить вас как игрока, пока один из них не поднялся на вершину.

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

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

Как это относится к программированию?

Помимо всех очевидных проблем безопасности потоков и синхронизации, которые могут быть изменены с помощью синглтонов ... Если у вас есть один набор данных, то есть способный одновременно считываться / управляться несколькими разными источниками и существовать в течение всего времени выполнения приложения, вероятно, самое подходящее время для того, чтобы отступить и спросить: «Я использую здесь правильный тип структуры данных».

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

. Синглтон - это только вариант, если вам нужно то, что обеспечивает один синглтон. Один экземпляр объекта только для чтения. Это же правило должно также каскадироваться к свойствам объекта / членам.

30
ответ дан 5 revs, 2 users 97% 16 August 2018 в 02:05
поделиться
  • 1
    Что делать, если singleton использует некоторые данные? – Yola 11 December 2014 в 07:54
  • 2
    @Yola Это сократило бы количество записей, если бы однотонный план должен был обновляться по заранее определенному и / или фиксированному расписанию, тем самым уменьшая конфликт потоков. Тем не менее, вы не сможете точно протестировать любой из кодов, взаимодействующих с синглоном, если вы не издеваетесь над экземпляром, отличным от одиночного, который имитирует одно и то же использование. Люди TDD, вероятно, подойдут, но это сработает. – Evan Plaice 15 December 2014 в 06:35
  • 3
    @EvanPlaice: Даже с макетом у вас возникнут проблемы с кодом, который говорит Singleton.getInstance(). Язык, который поддерживает отражение, мог бы обойти это, установив поле, где хранится Единый True экземпляр. ИМО, тем не менее, тесты становятся немного менее надежными после того, как вы отправились в обезьяну с частным состоянием другого класса. – cHao 9 January 2015 в 18:39

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

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

В сборке собранных мусора синглэты могут быстро стать проблемой в отношении управления памятью.

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

65
ответ дан 5 revs, 3 users 52% 16 August 2018 в 02:05
поделиться
  • 1
    Я знаю, что это многолетняя нить. Привет @ Кимоз у сказал: - синглтоны могут быстро стать проблемой в отношении управления памятью. хотел бы более подробно объяснить, какая проблема может возникнуть в отношении singleton & amp; вывоз мусора. – Thomas 4 April 2014 в 15:09
  • 2
    @Kimoz, вопрос задает «Почему одиночный шаблон не является проблемой сам по себе? & Quot; , и вы просто повторили эту точку, но не предоставили ни одного действительного примера использования одноэлементного шаблона. – Pacerier 25 June 2014 в 02:24
  • 3
    @Thomas, потому что одноэлемент по определению существует только в одном экземпляре. Таким образом, часто сложно назначить единственную ссылку на null. Это можно сделать, но это означает, что вы полностью контролируете точку, после которой синглтон не используется в вашем приложении. И это редко, и, как правило, совершенно противоположно тому, что ищет энтузиаст singleton: простой способ сделать единственный экземпляр always доступным. На некоторых DI-фреймах, таких как Guice или Dagger, невозможно избавиться от синглтона, и он остается навсегда в памяти. (Хотя контейнеры, предоставляемые синглтонами, намного лучше, чем домашние). – Snicolas 28 May 2015 в 04:49

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

Я считаю, что обратная реакция вызвана чрезмерным использованием, которое, в свою очередь, из-за того, что это самый простой шаблон для понимания и реализации.

11
ответ дан Ben Hoffstein 16 August 2018 в 02:05
поделиться
  • 1
    Я думаю, что обратная связь имеет больше общего с людьми, практикующими формализованные модульные тесты, понимая, что они являются кошмаром, с которым приходится иметь дело. – Jim Burger 26 September 2008 в 07:15
  • 2
    Не знаю, почему это на -1. Это не самый описательный ответ, но он тоже не ошибается. – Outlaw Programmer 26 September 2008 в 18:28

Я хотел бы ответить на 4 пункта в принятом ответе, надеюсь, кто-то может объяснить, почему я ошибаюсь.

  1. Почему скрывает зависимости в коде плохо? Уже есть десятки скрытых зависимостей (вызовы времени выполнения, вызовы OS API, глобальные вызовы функций) и односторонние зависимости легко найти (поиск экземпляра ()). «Сделать что-то глобальное, чтобы избежать его распространения, - это запах кода». Почему не происходит что-то вокруг, чтобы избежать лишнего запаха кода? Если вы передаете объект через 10 функций в стеке вызовов, чтобы избежать синглтона, это так здорово?
  2. Принцип единой ответственности: я думаю, что это немного расплывчато и зависит от вашего определения ответственности , Вопрос в том, почему добавление этой конкретной «ответственности» к классу имеет значение?
  3. Почему передача объекта в класс делает его более тесно связанным, чем с использованием этого объекта как одноэлемент изнутри класса?
  4. Почему он меняет, как долго длится состояние? Синглтоны могут быть созданы или уничтожены вручную, поэтому элемент управления все еще существует, и вы можете сделать его время жизни таким же, как и время жизни объекта, отличного от одного элемента.

Что касается модульных тестов:

  • не все классы должны быть подвергнуты блочному тестированию
  • не все классы, которые должны быть протестированы с помощью модуля, должны изменить реализацию singleton
  • , если они do нуждаются в модульном тестировании и необходимо изменить реализацию, легко изменить класс с использованием одноэлементного режима на то, чтобы один синглет был передан ему через инъекцию зависимостей.
14
ответ дан Jon 16 August 2018 в 02:05
поделиться
  • 1
    1. Все эти скрытые зависимости? Это тоже плохо. Скрытые зависимости всегда злые. Но в случае ЭЛТ и ОС они уже есть, и это единственный способ сделать что-то. (Попробуйте написать программу C без использования среды выполнения или ОС.) Эта способность делать вещи значительно перевешивает их негативы. Синглтоны в нашем коде не получают эту роскошь; так как они прочно входят в сферу контроля и ответственности, каждое использование (прочитайте: каждая дополнительная скрытая зависимость) должно быть оправдано, как единственный разумный способ добиться результата. Очень, very немногие из них на самом деле. – cHao 12 February 2013 в 16:17
  • 2
    2. «Ответственность». обычно определяется как «причина для изменения». Синглтон заканчивает как управление своей жизнью, так и выполнением своей реальной работы. Если вы изменили способ выполнения задания или , как строится граф объектов, вам необходимо изменить класс. Но если у вас есть другой код, постройте граф объекта, и ваш класс просто выполнит свою настоящую работу, этот код инициализации может настроить граф объектов, как бы он ни понравился. Все гораздо более модульное и проверяемое, потому что вы можете вставлять тестовые двойники и все разрывать по своему усмотрению, и вы больше не полагаетесь на скрытые движущиеся части. – cHao 12 February 2013 в 16:39
  • 3
    @cHao: 1. Хорошо, что вы признаете, что «способность делать вещи значительно перевешивает их негативы». Примером может служить структура ведения журнала. Зло поручить передачу глобального объекта ведения журнала путем инъекции зависимостей через уровни вызовов функций, если это означает, что разработчикам не рекомендуется выполнять регистрацию. Следовательно, singleton. 3. Тонкая точка соединения важна только в том случае, если вы хотите, чтобы клиенты класса контролировали поведение посредством полиморфизма. Это часто бывает не так. – Jon 14 February 2013 в 00:48
  • 4
    4. Я не уверен, что «невозможно уничтожить вручную». является логическим следствием "может быть только один экземпляр". Если это так, как вы определяете singleton, то мы не говорим об одном и том же. Все классы не должны быть протестированы. Это деловое решение, и иногда время выхода на рынок или стоимость разработки будут иметь приоритет. – Jon 14 February 2013 в 00:48
  • 5
    3. Если вам не нужен полиморфизм, вам даже не нужен экземпляр. Вы могли бы также сделать его статическим классом, потому что в любом случае вы привязываетесь к одному объекту и единичной реализации - и по крайней мере тогда API вам не так много лжет. – cHao 14 February 2013 в 01:50

У Винса Хьюстона есть эти критерии, которые кажутся мне разумными:

Singleton следует рассматривать только в том случае, если удовлетворяются все три из следующих критериев:

  • Собственность одного экземпляра не может быть назначена надлежащим образом
  • Желательна инициализация в режиме ожидания
  • Глобальный доступ для
g6] Если принадлежность к одному экземпляру, когда и как происходит инициализация, а глобальный доступ не является проблемой, Singleton недостаточно интересен.

15
ответ дан js. 16 August 2018 в 02:05
поделиться

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

Часто программное обеспечение усложняется, имеет смысл иметь несколько независимых экземпляров класса «singleton» с различным состоянием. В таких случаях ошибочный код для простого захвата синглтона. Использование Singleton.getInstance () может быть в порядке для небольших простых систем, но оно не работает / масштабируется, когда ему может понадобиться другой экземпляр того же класса.

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

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

4
ответ дан mP. 16 August 2018 в 02:05
поделиться

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

Синглоты делают очень трудно переходить от них к обычным объектам.

Кроме того, слишком легко написать однопоточный однопоточный.

Вместо того, чтобы использовать синглтоны, вы должны передать все необходимые объекты полезности от функции к функции. Это можно упростить, если вы переместите все их в вспомогательный объект, например:

void some_class::some_function(parameters, service_provider& srv)
{
    srv.get<error_logger>().log("Hi there!");
    this->another_function(some_other_parameters, srv);
}
8
ответ дан Roman Odaisky 16 August 2018 в 02:05
поделиться
  • 1
    прохождение аргумента для каждого метода является блестящим, оно должно идти по крайней мере на 10 основных способов, как загрязнять ваш api. – Dainius 24 October 2014 в 12:34
  • 2
    Это очевидный недостаток и тот, который должен был обрабатываться языком, с помощью аргументов, которые каким-то образом распространяются на вложенные вызовы, но при отсутствии такой поддержки они должны выполняться вручную. Считайте, что даже естественные синглтоны, как объект, представляющий системные часы, могут иметь проблемы. Например, как вы собираетесь охватывать часы-зависимый код (подумайте о нескольких тарифах) с испытаниями? – Roman Odaisky 26 October 2014 в 14:23
  • 3
    зависит от того, что вы тестируете, если вы не тестируете синглтон, почему вы заботитесь о том, как он себя ведет, если ваш 2 удаленных объекта зависит от поведения друг друга, это не проблема одиночной проблемы. – Dainius 27 October 2014 в 17:32
  • 4
    Не могли бы вы указать, какой язык будет распространяться на вложенные вызовы? – Dainius 27 October 2014 в 17:33
  • 5
    Если у вас есть один модуль, который зависит от другого, и вы не знаете / не можете его записать, вам будет трудно, независимо от того, является ли он одиночным или нет. Люди часто используют метод наследования, где они должны использовать композицию, но вы не говорите, что наследование плохое, и ООП следует избегать любой ценой, потому что так много людей делают ошибки дизайна там, или вы? – Dainius 29 October 2014 в 14:50

Синглтоны НЕ плохо. Это плохо, когда вы делаете что-то глобально уникальным, что не является глобально уникальным.

Однако существуют «службы области приложения» (подумайте о системе обмена сообщениями, которая заставляет компоненты взаимодействовать) - это CALLS для одноэлементного, класс «MessageQueue», который имеет метод «SendMessage (...)».

Затем вы можете делать следующее со всех сторон:

MessageQueue.Current.SendMessage (new MailArrivedMessage (...));

И, конечно же, выполните:

MessageQueue.Current.RegisterReceiver (this);

в классах, которые реализовать IMessageReceiver.

6
ответ дан StormianRootSolver 16 August 2018 в 02:05
поделиться
  • 1
    И если я хочу создать вторую очередь сообщений с меньшей областью, почему бы мне не позволить повторно использовать код для его создания? Одноэлемент предотвращает это. Но если вы только что создали обычный класс очереди сообщений, а затем создали один глобальный экземпляр, чтобы действовать как «область приложения», один, я мог бы создать второй экземпляр для другого использования. Но если вы сделаете класс singleton, мне придется написать класс очереди сообщений second . – jalf 10 November 2010 в 15:39
  • 2
    Также почему мы не должны иметь глобальный CustomerOrderList, поэтому мы можем назвать это красиво из любой точки, например MessageQueue? Я считаю, что ответ одинаковый для обоих: он эффективно создает глобальную переменную. – LegendLength 6 January 2016 в 03:32

Синглтоны также плохи, когда дело доходит до кластеризации. Потому что тогда у вас больше нет «одного синглтона» в вашем приложении.

Рассмотрим следующую ситуацию: как разработчик вам необходимо создать веб-приложение, которое обращается к базе данных. Чтобы гарантировать, что одновременные вызовы базы данных не конфликтуют друг с другом, вы создаете thread-save SingletonDao:

public class SingletonDao {
    // songleton's static variable and getInstance() method etc. omitted
    public void writeXYZ(...){
        synchronized(...){
            // some database writing operations...
        }
    }
}

. Таким образом, вы уверены, что в вашем приложении существует только один синглтон, и вся база данных проходит через это один и только SingletonDao. Теперь ваша рабочая среда выглядит следующим образом: Single Singleton [/g0]

До сих пор все в порядке.

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

Many singletons [/g1]

Это звучит странно, но теперь у вас много синглтонов в вашем приложении. И это именно то, что не должно быть одноэлементным: иметь множество объектов. Это особенно плохо, если вы, как показано в этом примере, хотите сделать синхронизированные вызовы в базу данных.

Конечно, это пример плохого использования одноэлементного кода. Но сообщение этого примера: вы не можете полагаться на то, что в вашем приложении есть только один экземпляр singleton, особенно когда дело касается кластеризации.

42
ответ дан Uooo 16 August 2018 в 02:05
поделиться
  • 1
    если вы не знаете, как реализовать синглтон, вы не должны этого делать. Если вы не знаете, что делаете, вы должны найти это во-первых, и только после этого сделайте то, что вам нужно. – Dainius 24 October 2014 в 12:30
  • 2
    Это интересно, у меня есть вопрос. Итак, что конкретно представляет собой проблема, если одиночные точки - каждый на другой машине / JVM - подключаются к одной базе данных? Область синглтонов предназначена только для конкретной JVM, и это все еще верно даже в кластере. Вместо того, чтобы просто философски заявлять, что эта конкретная ситуация плохая, потому что наше намерение было единственным объектом в приложении, я был бы рад увидеть любые технические проблемы, которые могут возникнуть из-за этой договоренности. – Saurabh Patil 20 October 2016 в 17:52

Образец появляется, когда несколько человек (или команды) приходят к аналогичным или идентичным решениям. Многие люди по-прежнему используют синглеты в своей первоначальной форме или используют фабричные шаблоны (хорошее обсуждение в Modern C ++ Design от Alexandrescu). Параллелизм и трудности в управлении временем жизни объекта являются основными препятствиями, при этом первый легко управляется, как вы предлагаете.

Как и все варианты, Singleton имеет свою долю взлетов и падений. Я думаю, что их можно использовать в умеренных количествах, особенно для объектов, которые выживают в течение срока службы приложения. Тот факт, что они напоминают (и, вероятно, есть) глобалы, предположительно выбрасывает пуристов.

4
ответ дан user22044 16 August 2018 в 02:05
поделиться

Вот еще одна вещь о одиночных играх, о которых никто еще не сказал.

В большинстве случаев «singletonity» является деталью реализации для некоторого класса, а не характеристикой его интерфейса. Inversion of Control Container может скрыть этот признак от пользователей класса; вам просто нужно отметить свой класс как одноэлементный (с аннотацией @Singleton в Java, например) и все; IoCC сделает все остальное. Вам не нужно предоставлять глобальный доступ к вашему экземпляру singleton, потому что доступ уже управляется IoCC. Таким образом, нет ничего плохого в IoC Singletons.

GoF Singletons в противоположность IoC Синглтоны должны выставлять «singletonity» в интерфейсе методом getInstance (), и поэтому они страдают от всего сказанного выше.

6
ответ дан Volodymyr Frolov 16 August 2018 в 02:05
поделиться
  • 1
    По-моему, "однотонность" является детальностью среды выполнения и не должна рассматриваться программистом, который написал код класса. Скорее, это будет рассматриваться классом USER. только USER знает, сколько экземпляров действительно требуется. – Earth Engine 12 April 2013 в 05:50

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

4
ответ дан Ycros 16 August 2018 в 02:05
поделиться
  • 1
    Если вы не ограничены экземпляром экземпляра, вам понадобятся статические члены в вашем классе, управляемые семафорами, которые выходят примерно в одно и то же! Какова ваша предлагаемая альтернатива? – Jeach 18 February 2010 в 16:21
  • 2
    У меня огромное приложение с «MainScreen». этот экран открывает много более мелких модальных / немодульных окон / форм пользовательского интерфейса. IMHO Я чувствую, что MainScreen должен быть синглом, так что, например, виджет где-то в дальнем углу приложения хочет показать свой статус в строке состояния MainScreen, все, что он должен сделать, это MainScreen.getInstance (). SetStatus ( «Некоторый текст»); Что вы предлагаете в качестве альтернативы? Пропустить MainScreen по всему приложению? : D – Salvin Francis 6 April 2010 в 09:59
  • 3
    @SalvinFrancis: Я бы порекомендовал, что вы перестаете иметь объекты, которые заботятся о вещах, которые им не нужны, и пробираться через приложение, чтобы обходиться друг с другом. :) Ваш пример будет намного лучше с событиями. Когда вы делаете события правильно, виджет даже не заботится о том, есть ли вообще MainScreen; он просто передает «эй, что-то случилось» и независимо от того, что подписались на «материал», (будь то MainScreen, WidgetTest или что-то еще!) решает, как он хочет ответить. В любом случае, ООП предполагается . :) – cHao 26 February 2013 в 23:48
  • 4
    @Salvin Подумайте, как трудно рассуждать о MainScreen при отладке, если он «тихо» обновляется многими компонентами. Ваш пример - прекрасная причина, почему одиночные игры плохи. – LegendLength 6 January 2016 в 03:35

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

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

FWIW, если это PIA, когда вы пытаетесь выполнить его тестирование, тогда он отправится в PIA, когда вы попытаетесь отладить ошибку исправить или улучшить его.

104
ответ дан 2 revs, 2 users 67% 16 August 2018 в 02:05
поделиться
  • 1
    не являются ли весенние бобы, по умолчанию, Singletons? – slim 8 February 2010 в 16:50
  • 2
    Да, но я имею в виду «кодирование» синглетов. Я не написал «singleton» (т. Е. С частным конструктором yada yada yada в соответствии с шаблоном проектирования), но да, с весной я использую один экземпляр. – prule 16 February 2010 в 20:59
  • 3
    Что это за один экземпляр, доступный во всем приложении? Ой. <Я> Global . «Синглтон» является , а не шаблоном для обертывания глобальных символов ». является либо наивным, либо вводящим в заблуждение, поскольку по определению , шаблон обертывает класс вокруг глобального экземпляра. – cHao 19 February 2013 в 09:10
  • 4
    Мой опыт в том, что запуск с синглонами действительно повредит вам даже в краткосрочной перспективе, не считая длительный пробег. Этот эффект может быть мне меньше, если приложение уже существует в течение некоторого времени и, вероятно, уже заражено другими синглетонами. Начиная с нуля? Избегайте их любой ценой! Хотите один экземпляр объекта? Позвольте фабрике управлять созданием этого объекта. – Sven 17 May 2013 в 20:36
  • 5
    AFAIK Singleton является заводским методом. Таким образом, я не получаю вашу рекомендацию. – tacone 17 May 2013 в 23:37
  • 6
    "Завод" ! = "Factory_method, который не может быть отделен от другого полезного материала в том же классе" – Sven 18 May 2013 в 01:12
  • 7
    Это скорее похоже на проблему с модульным тестированием, которое может тестировать объекты (единицы), функции (единицы), целые библиотеки (единицы), но не с чем-либо статическим в классе (также единицами). – v010dya 3 February 2014 в 06:35
  • 8
    Конечно, вы можете создавать один экземпляр класса при запуске приложения и вводить этот экземпляр через интерфейс во все, что его использует. Реализация не должна волновать, что может быть только один. – Scott Whitlock 31 March 2014 в 20:33
  • 9
    вы не думаете, все равно, чтобы все внешние ссылки? Если да, то какая проблема для moc singleton, если нет, действительно ли вы выполняете модульное тестирование? – Dainius 24 October 2014 в 12:28
  • 10
    поэтому, когда другие это делают, это нормально (если я буду использовать это после), но если другие это сделают, и я не буду использовать его, это зло? – Dainius 24 October 2014 в 12:32
  • 11
    @Dainius: В конце концов, на самом деле нет. Конечно, вы не можете произвольно заменить экземпляр на другой. (За исключением тех моментов, вызывающих facepalm, когда вы делаете . Я уже видел методы setInstance раньше.) Это вряд ли имеет значение, однако, - что weenie, который «нужен», синглтон также не знал ничего необычного в инкапсуляции или что не так с изменчивым глобальным состоянием, поэтому он с благодарностью (?) предоставлял сеттеры для каждого. Один. поле. (И да, это происходит. lot . Почти каждый синглтон, который я когда-либо видел в дикой природе, был изменчив по дизайну и часто смущающе.) – cHao 8 January 2015 в 06:42
  • 12
    @Dainius: В значительной степени у нас уже есть. «Предпочтительная композиция по наследованию» это уже давно. Если наследование является лучшим решением, вы, конечно, можете его использовать. То же самое происходит с синглонами, глобалями, потоками, goto и т. Д. Во многих случаях они могут работать , но, откровенно говоря, «работает». недостаточно - если вы хотите идти против общепринятой мудрости, вам лучше продемонстрировать, как ваш подход лучше , чем обычные решения. И я еще не видел такого случая для шаблона Singleton. – cHao 11 January 2015 в 00:20
  • 13
    @Dainius: Mocking экземпляры намного меньше проблем, чем насмешливые классы. Вы могли бы, вероятно, извлечь тестируемый класс из остальной части приложения и протестировать поддельный класс Singleton. Однако это очень усложняет процесс тестирования. Например, теперь вам нужно иметь возможность разгружать классы по своему усмотрению (на самом деле это не вариант на большинстве языков) или запускать новую виртуальную машину для каждого теста (чтение: тесты могут занимать тысячи раз). Для двоих, однако, зависимость от Singleton - это деталь реализации, которая теперь протекает по всем вашим тестам. – cHao 11 January 2015 в 04:07
  • 14
    Чтобы мы не разговаривали друг с другом, я говорю не только о глобально доступном экземпляре. Для этого есть много случаев. То, о чем я говорю (особенно, когда я говорю «capital-S Singleton»), является шаблоном Singleton GoF, который вставляет этот единственный глобальный экземпляр в сам класс, предоставляет его с помощью метода getInstance или аналогичного имени и предотвращает существование второго экземпляра. Честно говоря, в этот момент вы могли бы даже не иметь экземпляр one . – cHao 12 January 2015 в 13:30
  • 15
    Powermock может издеваться над статическим материалом. – Snicolas 28 May 2015 в 04:50
  • 16
    делает издевательство над объектом, создавая реальный объект? Если издевательство не создает реального объекта, то почему имеет значение, является ли класс singleton или метод статическим? – Arun Raaj 13 August 2018 в 11:12
Другие вопросы по тегам:

Похожие вопросы: