Как правило, я избегаю синглетов, потому что они затрудняют тестирование вашего приложения. Синглтоны трудно объединиться для модульных тестов именно из-за их характера - вы всегда получаете то же самое, а не одно, которое вы легко конфигурируете для модульного теста. Конфигурационные данные - строго типизированные данные конфигурации, во всяком случае - это одно исключение, которое я делаю. Как правило, данные конфигурации относительно статичны в любом случае, и альтернатива предполагает запись достаточного количества кода, чтобы избежать статических классов, которые обеспечивает инфраструктура для доступа к web.config.
Существует несколько способов его использования, которые по-прежнему позволят вам выполнить тестирование вашего приложения. Один из способов (возможно, оба способа, если ваш синглтон не лениво читает app.cofnig) должен иметь файл app.config по умолчанию в вашем проектном модульном проекте, предоставляющем значения по умолчанию, необходимые для ваших тестов. Вы можете использовать рефлексию для замены любых конкретных значений по мере необходимости в модульных тестах. Как правило, я настраивал бы частный метод, который позволяет удалить отдельный экземпляр singleton в тестовой настройке, если я вношу изменения для конкретных тестов.
Другой способ заключается в том, что на самом деле не использовать Singleton напрямую, а создать для него интерфейс, который реализует класс singleton. Вы можете использовать ручную инъекцию интерфейса, по умолчанию для экземпляра singleton, если заданное значение равно null. Это позволяет создать экземпляр mock, который вы можете передать тестируемому классу для своих тестов, но в вашем реальном коде используется экземпляр singleton. По сути, каждый класс, который в нем нуждается, поддерживает частную ссылку на экземпляр singleton и использует его. Мне нравится этот способ немного лучше, но поскольку синглтон будет создан, вам все равно может понадобиться файл app.config по умолчанию, если все значения не будут загружены лениво.
public class Foo
{
private IAppConfiguration Configuration { get; set; }
public Foo() : this(null) { }
public Foo(IAppConfiguration config)
{
this.Configuration = config ?? AppConfiguration.Instance;
}
public void Bar()
{
var value = this.Config.SomeMaximum;
...
}
}
Возможный дубликат [Существуют ли жизнеспособные альтернативы шаблону Singleton в GOF?] (Http://stackoverflow.com/questions/162042/are-there-any-viable-alternatives-to-the-gof-singleton- pattern) –