То, что вы смотрите здесь, на самом деле не столько связано с шаблоном репозитория, само по себе , а больше связано с «внедрением зависимости», где внешние вещи, от которых зависит этот класс «вводятся» извне, а не создаются внутри (например, путем вызова new Repository()
).
В этом конкретном примере показана «инъекция конструктора», в которой зависимости внедряются при создании объекта. Это удобно, потому что вы всегда можете знать, что объект находится в определенном состоянии (что у него есть реализация репозитория). С таким же успехом вы можете использовать внедрение свойств, где вы предоставляете открытый установщик для назначения репозитория или другой зависимости. Это лишает заявленного преимущества внедрения в конструктор и несколько менее очевидно при проверке кода, но контейнер с инверсией управления может справиться с работой создания экземпляров объектов и внедрения зависимостей в конструктор и / или свойства.
Это способствует правильной инкапсуляции и существенно улучшает тестируемость.
Тот факт, что вы не создаете экземпляры коллабораторов в классе, это то, что улучшает тестируемость (вы можете изолировать поведение класса, вводя экземпляры-заглушки или макеты при тестировании).
Ключевое слово здесь, когда речь идет о шаблоне хранилища, - это инкапсуляция. Шаблон репозитория берет все эти данные для доступа к данным и скрывает их от классов, использующих репозиторий. Даже если ORM может скрывать всю реальную работу CRUD, вы все равно связаны с реализацией ORM. Хранилище может выступать в качестве фасада или адаптера, предлагая абстрактный интерфейс для доступа к объектам.
Итак, когда вы берете эти концепции вместе, у вас есть класс контроллера, который не обрабатывает сам доступ к данным и не создает экземпляр хранилища для его обработки. Скорее контроллер принимает внедренный репозиторий и знает только интерфейс. В чем выгода? Вы можете полностью изменить свой доступ к данным и никогда не трогать контроллер.
Если перейти к вашему вопросу, репозиторий является зависимостью, и он предоставляется в конструкторе по причинам, изложенным выше. Если у вас есть дальнейшая зависимость от CategoryRepository
, тогда да, во что бы то ни стало внедрите это и в конструктор.
В качестве альтернативы, вы можете предоставить фабричные классы как зависимости - опять же классы, которые реализуют некоторый фабричный интерфейс, но вместо самой зависимости это класс, который знает, как создать зависимость. Может быть, вы хотите другой IDinnerRepository
для разных ситуаций. Фабрика может принять параметр и вернуть реализацию в соответствии с некоторой логикой, и, поскольку это всегда будет IDinnerRepository
, контроллер не должен знать, что на самом деле делает этот репозиторий.