Синглтон для настройки приложения

До сих пор во всех моих проектах я использовал одноэлементный шаблон для доступа к конфигурации приложения во всем приложении. В последнее время я вижу много статей о том, чтобы не использовать шаблон singleton, потому что этот шаблон не способствует тестируемости, а также скрывает зависимость Component. У меня вопрос: как лучше всего хранить конфигурацию приложения, которая легко доступна во всем приложении, не передавая объект конфигурации по всему приложению?

Заранее спасибо

Мадху


person madhu    schedule 17.12.2008    source источник


Ответы (6)


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

РЕДАКТИРОВАТЬ Мы живем и учимся. Хотя я считаю, что конфигурация приложения - одно из немногих мест, где можно использовать синглтон, я больше этим не занимаюсь. Обычно сейчас я создаю интерфейс и стандартную реализацию класса, используя статические Lazy<T> поля поддержки для свойств конфигурации. Это позволяет мне иметь поведение «инициализировать один раз» для каждого свойства с лучшей проверкой тестируемости.

person tvanfosson    schedule 17.12.2008
comment
+1, люди ДЕЙСТВИТЕЛЬНО любят создавать свои маленькие правила, например, только один выход из цикла или запрещение синглтонов. Я бы предпочел быть прагматиком, а не догматиком, поскольку догма приводит к тому, что люди не могут думать самостоятельно. Если у вас может быть только один объект X, у вас должен быть только один объект XConfig. - person paxdiablo; 17.12.2008
comment
Наличие единственного экземпляра объекта конфигурации - это хорошо и желательно, но это не значит, что использование синглтона для его улучшения. Использование хаков, таких как конкретные методы тестирования в вашем реальном классе, также не подходит для чистого кода или тестов. - person ColinD; 19.12.2008
comment
У вас есть пример новой реализации с интерфейсом и стандартным классом, использующим static? - person Gabrielizalo; 19.07.2018
comment
@tvanfosson, лучше, если вы включите сюда новый пример. Я не понял. - person s1n7ax; 03.11.2020

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

person ColinD    schedule 18.12.2008
comment
Таким образом, в этом случае объект конфигурации будет по-прежнему одноэлементным, но код будет использовать интерфейс, а не непосредственно класс, а фактическая реализация будет внедрена Spring? Таким образом, мы могли внедрить фиктивный объект для тестирования. Это правильно? - person stivlo; 28.05.2011
comment
@stivlo: Правильно, единственный экземпляр будет управляться контейнером внедрения зависимостей (будь то Spring, Guice или что-то еще), и код, возможно, может использовать интерфейс, позволяющий вам передать реализацию, которую вы делаете, с настройками, которые вы хотите для тестирования . Это не обязательно должна быть фикция ... это может быть настоящая реализация, просто с настройками, которые вы добавляете сами, а не читаете из файла. - person ColinD; 29.05.2011
comment
Итак, @ColinD, пожалуйста, подождите, все внимание здесь не в том, что Синглтон вреден для себя, он может быть уместным, особенно для конфигурации приложения или, возможно, для поддержания пула соединений, я бы сказал, но он может стать плохим, когда зависимость скрыта, поэтому мы не видим зависимости кода. Установка этой зависимости с помощью контейнера внедрения зависимости делает ее явной. Такой вывод немного отличается от догмы избегать одиночек, согласны ли вы с ним? - person stivlo; 29.05.2011
comment
@stivlo: когда я говорю синглтон, я имею в виду отдельный экземпляр определенного класса в приложении, а не шаблон проектирования синглтон (который использует статический экземпляр класса). Шаблон проектирования синглтонов - это то, о чем идет речь, хотя синглтоны в целом, вероятно, слишком часто используются, когда более тонкий прицел был бы лучше. Что касается явной зависимости от скрытой: да, это одна из нескольких веских причин использовать внедрение зависимостей, а не шаблон Singleton. - person ColinD; 29.05.2011

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

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

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

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

Что касается конфигурации приложения, я думаю, было бы безопасно оставить все как есть.

person OscarRyz    schedule 17.12.2008

Похоже, что одноэлементный шаблон - лучший вариант. Вот написанный мной Setting класс, который мне подходит.

person Protagonist    schedule 01.03.2009

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

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

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

person user2366975    schedule 18.04.2020

Вот пример, сделанный с использованием Castale.Core >> DictionaryAdapter и StructureMap

person ruslander    schedule 04.03.2011
comment
ссылка больше не действительна - person s1n7ax; 03.11.2020