Вопрос

А одноэлементный шаблон является полностью оплаченным членом ГоФ's книга узоров, но в последнее время мир разработчиков кажется довольно осиротевшим.Я до сих пор использую довольно много синглтонов, особенно для заводские классы, и хотя с проблемами многопоточности нужно быть немного осторожными (как и с любым классом), я не понимаю, почему они так ужасны.

Особенно похоже, что Stack Overflow предполагает, что все согласны с тем, что синглтоны — это зло.Почему?

Пожалуйста, подтвердите свои ответы значком "факты, ссылки или конкретный опыт"

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

Решение

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

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

  2. Они нарушают принцип единой ответственности:в силу того, что они контролируют свое собственное создание и жизненный цикл.

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

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

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

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

Конфликт за ресурсы.

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

(1) может иметь только один экземпляр, и

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

тебе необходимо синглтон.

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

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

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

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

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

У Миско Хевери из Google есть несколько интересных статей именно на эту тему...

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

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

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

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

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

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

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

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

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

скорее, чем:

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

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

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

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

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

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

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

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

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

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

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

Итак, вы уверены, что в вашем приложении существует только один синглтон и вся база данных проходит через него. SingletonDao.Ваша производственная среда теперь выглядит так:Single Singleton

Пока все в порядке.

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

Many singletons

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

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

  1. Его легко (ab) использовать как глобальную переменную.
  2. Классы, которые зависят от синглтонов, сравнительно сложнее тестировать по отдельности.

Монополия — это дьявол, а синглтоны с состоянием, не доступным только для чтения/изменяемым, — это «настоящая» проблема…

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

Глобальный — это плохо, потому что:

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

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

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

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

Как это применимо к «Монополии»?

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

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

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

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

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

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

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

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

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

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

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

Синглтон — это не единственный экземпляр!

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

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

Как я уже говорил в заголовке, синглтон не относится к одному экземпляру.

  • Синглтоны улучшают читаемость:Вы можете посмотреть на свой класс и посмотреть, какой синглтон он внедрил, чтобы выяснить, каковы его зависимости.
  • Singletons улучшает обслуживание:После того, как вы удалили зависимость из класса, вы просто удалили какую-то одноэлементную инъекцию, вам не нужно идти и редактировать большую ссылку на другие классы, которые только что переместили вашу зависимость (для меня это вонючий код). @Джим Бургер)
  • Синглтоны улучшают память и производительность:Когда что-то происходит в вашем приложении и для доставки требуется длинная цепочка обратных вызовов, вы тратите впустую память и производительность. Используя Singleton, вы отсекаете посредников и улучшаете свою производительность и использование памяти (избегая ненужного выделения локальных переменных). ).

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

Две самые большие ошибки, которые я вижу:относиться к нему как к глобальному и не определять замыкание Singleton.

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

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

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

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

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

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

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

Ссылки (только актуальные ссылки из статьи)

  1. ^ Алекс Миллер. Узоры, которые я ненавижу №1:Синглтон, июль 2007 г.
  2. ^ Скотт Денсмор. Почему одиночки – это зло, май 2004 г.
  3. ^ Стив Йегге. Одиночки считаются глупыми, сентябрь 2004 г.
  4. ^ Дж.Б.Райнсбергер, IBM. Используйте свои синглтоны с умом, июль 2001 г.

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

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

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

  2. Убедитесь, что Singleton является потокобезопасным.Это данность.

  3. Синглтон должен быть простым по своей природе и не слишком сложным.

  4. Во время выполнения приложения, когда синглтоны должны быть переданы данному объекту, используйте фабрику классов, которая создает этот объект, и пусть фабрика классов передает экземпляр синглтона классу, которому он нужен.

  5. Во время тестирования и для обеспечения детерминированного поведения создайте одноэлементный класс как отдельный экземпляр либо в виде самого фактического класса, либо в качестве заглушки/макета, реализующего его поведение, и передайте его как есть классу, которому он требуется.Не используйте фактор класса, который создает тестируемый объект, которому во время тестирования требуется синглтон, поскольку он будет передавать единственный его глобальный экземпляр, что противоречит цели.

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

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

Синглтон следует рассматривать только в том случае, если соблюдены все три из следующих критериев:

  • Право собственности на один экземпляр не может быть разумно передано
  • Ленивая инициализация желательна
  • Глобальный доступ иначе не предусмотрен

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

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

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

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

    Если вы передаете объект через 10 функций в стеке вызовов только для того, чтобы избежать синглтона, разве это здорово?

  2. Принцип единой ответственности:Я думаю, что это немного расплывчато и зависит от вашего определения ответственности.Уместным будет вопрос: почему добавление этого специфический «ответственность» за классовое дело?

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

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

По поводу модульных тестов:

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

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

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

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

Синглетоны плохи с пуристской точки зрения.

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

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

Синглтоны иногда также усложняют модульное тестирование.

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

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

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

Из-за синглтонов очень сложно перейти от них к обычным объектам.

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

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

void some_class::some_function(parameters, service_provider& srv)
{
    srv.get<error_logger>().log("Hi there!");
    this->another_function(some_other_parameters, srv);
}

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

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

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

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

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

http://geekswithblogs.net/AngelEyes/archive/2013/09/08/singleton-i-love-you-but-youre-bringing-me-down-re-uploaded.aspx

Вот еще кое-что о синглтонах, о котором еще никто не сказал.

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

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

Синглтоны НЕ плохие.Плохо только, когда ты делаешь что-то глобально уникальное, но не глобально уникальное.

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

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

MessageQueue.Current.SendMessage(новый MailArrivedMessage(...));

И, конечно же, сделайте:

MessageQueue.Current.RegisterReceiver(это);

в классах, реализующих IMessageReceiver.

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

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

Паттерн возникает, когда несколько людей (или команд) приходят к схожим или идентичным решениям.Многие люди до сих пор используют синглтоны в их исходной форме или используют фабричные шаблоны (хорошее обсуждение в книге Александреску «Современный дизайн C++»).Основными препятствиями являются параллелизм и сложность управления временем жизни объекта, причем с первыми легко справиться, как вы предлагаете.

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

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

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

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

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

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