Это неправильное использование синглтона?

1

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

По существу у меня есть 5 репозиториев. Все, что они делают, это данные хранилища. На самом деле все хранящиеся в них данные тесно связаны, я только сделал их 5 разных репозиториев, чтобы классы были короткими и легкими в выборе. Я знаю, что если я сделаю каждый из этих репозиториев одним синглом, я могу сказать до свидания с любыми поддерживаемыми модульными тестами; Однако; У меня была эта идея, что я могу сделать каждый репозиторий нормальным классом, а затем создать синглтон, который просто хранит 1 копию каждого из репозиториев.

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

Теги:
design-patterns
singleton
design

2 ответа

2
Лучший ответ

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

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

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

  • 0
    Согласитесь, рассмотрите возможность использования контейнера IOC для внедрения репозиториев. Вы можете контролировать их время жизни в корне композиции, указав синглтон на данный момент с возможностью довольно легко изменить это решение позже.
  • 1
    @ jayint32: спасибо за комментарий! Я согласен, но я обычно держу контейнерную часть вне поля зрения, так как лучшее место для его использования - это корень композиции , а это означает, что все остальные части кода должны работать так, как будто контейнера вообще не было (я пытаюсь чтобы избежать шаблона локатора службы), и он не нужен для модульного тестирования. Даже DI бедного человека будет работать отлично, ИМХО, после того, как остальная часть приложения будет построена правильно.
Показать ещё 1 комментарий
0

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

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

Рассмотрите эту возможную замену;

   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, но принципы должны применяться)

  • 0
    Как именно это упростит тестирование? Я не вижу ни одного преимущества от использования одноэлементного Application.Current для доступа к пользовательскому экземпляру, производному от Application , и добавления функциональности доступа к данным в этот совершенно не связанный класс. И это все еще одиночка.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню