У нас есть класс, который содержит информацию о конфигурации приложения. Раньше это был синглтон. После некоторого обзора архитектуры нам сказали удалить синглтон. Мы действительно увидели некоторые преимущества отказа от использования синглтона в модульном тестировании, потому что мы можем тестировать разные конфигурации одновременно.
Без синглтона мы должны передавать экземпляр повсюду в нашем коде. Становится так запутанно, что мы написали синглтон-оболочку. Теперь мы переносим тот же код на PHP и .NET, и мне интересно, есть ли лучший шаблон, который мы можем использовать для объекта конфигурации.
источник
Лучше всего использовать вместо этого шаблон Factory. Когда вы создаете новый экземпляр своего класса (в фабрике), вы можете вставить «глобальные» данные во вновь созданный объект либо как ссылку на единственный экземпляр (который вы храните в фабричном классе), либо скопировав соответствующий данные в новый объект.
Тогда все ваши объекты будут содержать данные, которые раньше жили в синглтоне. Я не думаю, что в целом есть большая разница, но это может облегчить чтение вашего кода.
источник
Я мог бы сказать очевидное здесь, но есть ли причина, по которой вы не можете использовать структуру внедрения зависимостей, такую как Spring или Guice ? (Я считаю, что Spring теперь также доступен для .NET).
Таким образом, фреймворк может содержать единственную копию объектов конфигурации, и вашим bean-компонентам (службам, DAO и т. Д.) Не нужно беспокоиться о поиске их.
Я обычно придерживаюсь этого подхода!
источник
Если вы используете Spring Framework , вы можете просто создать обычный компонент. По умолчанию (или если вы явно задали
scope="singleton"
) создается только один экземпляр bean-компонента, и этот экземпляр возвращается каждый раз, когда bean-компонент используется в зависимости или извлекается черезgetBean()
.Вы получаете преимущество единственного экземпляра без привязки к шаблону Singleton.
источник
Альтернатива - передать то, что вам нужно, вместо того, чтобы просить объект о вещах.
источник
не накапливайте ответственность за один объект конфигурации, так как он заканчивается очень большим объектом, который трудно понять и хрупко.
Например, если вам нужен другой параметр для определенного класса, вы меняете
Configuration
объект, а затем перекомпилируете все классы, которые его используют. Это несколько проблематично.Попробуйте провести рефакторинг своего кода, чтобы избежать общих, глобальных и больших
Configuration
объектов. Передавать клиентским классам только необходимые параметры:следует отремонтировать на:
рамки инъекции зависимостей поможет много здесь, но это не stricly требуется.
источник
Вы можете добиться того же поведения синглтона, используя статические методы. Стив Йегге очень хорошо объясняет это в этом посте.
источник
Возможен ли класс, содержащий только статические методы и поля? Я не совсем уверен в вашей ситуации, но, возможно, стоит изучить ее.
источник
Зависит от того, какие инструменты / фреймворки и т. Д. Используются. С помощью инструментов внедрения зависимостей / ioc можно часто по-прежнему получить производительность / оптимизацию одноэлементного объекта, если контейнер di / ioc использует одноэлементное поведение для требуемого класса (например, интерфейс IConfigSettings), создав только один экземпляр класса. Это все еще можно заменить для тестирования
В качестве альтернативы можно использовать фабрику для создания класса и возврата одного и того же экземпляра каждый раз, когда вы его запрашиваете, но для тестирования он может вернуть заглушенную / имитацию версии.
источник
Проверьте возможность настройки в качестве интерфейса обратного вызова. Таким образом, ваш чувствительный к конфигурации код будет выглядеть:
Код инициализации системы будет выглядеть:
источник
Вы можете использовать среду внедрения зависимостей, чтобы облегчить боль при передаче объекта конфигурации. Достойным является ninject , преимущество которого заключается в использовании кода, а не xml.
источник
Возможно, тоже не очень чисто, но вы могли бы передать биты информации, которые хотите изменить, методу, который создает синглтон, вместо использования
вы можете вызвать его
createSingleton(Information info)
непосредственно при запуске приложения (и в методах setUp модульных тестов).источник
Синглтоны - это не зло, но шаблон проектирования ошибочен. У меня есть класс, в котором я хочу создать только один экземпляр во время выполнения, но хочу создать несколько изолированных экземпляров во время модульного тестирования, чтобы гарантировать детерминированные результаты.
DI с использованием Spring и т. Д. - очень хороший вариант, но не единственный.
источник