Я читал все о одиночных играх и о том, как они представляют угрозу для анти-шаблонов, если их неправильно использовать. Поэтому я хотел получить второе мнение относительно того, является ли это неправильным использованием шаблона.
По существу у меня есть 5 репозиториев. Все, что они делают, это данные хранилища. На самом деле все хранящиеся в них данные тесно связаны, я только сделал их 5 разных репозиториев, чтобы классы были короткими и легкими в выборе. Я знаю, что если я сделаю каждый из этих репозиториев одним синглом, я могу сказать до свидания с любыми поддерживаемыми модульными тестами; Однако; У меня была эта идея, что я могу сделать каждый репозиторий нормальным классом, а затем создать синглтон, который просто хранит 1 копию каждого из репозиториев.
Таким образом, я могу выполнить требования, что только одно центральное расположение для данных на экземпляр моей программы, но я также могу тестировать каждый репозиторий в некоторых операциях, которые он должен выполнять.
Разумеется, вы можете тестировать репозитории, но вам, безусловно, потребуется жесткая единица тестирования всего другого кода, который зависит от этих репозиториев. Синглтон соединяет вызывающий код с единственной реализацией через прямой доступ, разбросанный по всей вашей базе кода. И даже если на самом деле есть одна копия ваших данных, т.е. Какая-либо база данных в памяти, нет оснований позволять другим уровням это знать.
Кроме того, "делая их простым классом" (я полагаю, вы имеете в виду, разоблачая публичный конструктор?), Вы побеждаете всю точку синглтона, то есть идею о том, что никакой другой код не может создать экземпляр другого экземпляра.
Если репозитории являются зависимостью для определенного класса, то просто передайте их с помощью инъекции конструктора и упростите тестирование. Это позволит вам легко высмеять каждый репозиторий при тестировании классов из уровня домена.
То, что составляет злоупотребление синглоном (или вообще его полезность), является одним из тех религиозных аргументов, которые не имеют четкого ответа.
Однако вы столкнулись с одним из основных недостатков одноэлементного шаблона, и это то, что он усложняет модульные тесты. Хуже того, это в целом снижает общую ремонтопригодность вашего кода.
Рассмотрите эту возможную замену;
public interface IRepositoryContainer
{
IRepository GetRepository<T>() where T : IRepository;
}
public partial class App : Application, IRepositoryContainer
{
private List<IRepository> repositories =
new List<IRepository>() { new MyRespository() };
public IRepository GetRepository<T>()
where T : IRepository
{
return repositories.Where(t => t is T).SingleOrDefault();
}
то где раньше вы бы назвали синглтон, вместо этого...
IRepository repo = (Application.Current as IRepositoryContainer).GetRepository<MyRespository>();
Просто мысль, но есть только один экземпляр приложения, интерфейсы могут помочь вам решить эту проблему.
(да, код примера выше wpf, но принципы должны применяться)
Application.Current
для доступа к пользовательскому экземпляру, производному от Application
, и добавления функциональности доступа к данным в этот совершенно не связанный класс. И это все еще одиночка.