Шаблон репозитория и общие объекты

Я рассматриваю возможность использования шаблона проектирования репозитория для абстракции данных, использую PHP-инфраструктуру Phalcon и использую следующую структуру:

ModelA
|- Entity
|- Entity1.php
|- Entity2.php
|- Entity3.php
|- Repository
|- RepositoryA.php
|- Service
|- ServiceA.php

Теперь, если бы мне пришлось использовать тот же Entity2.php в другой ModelB, например, я бы потерял наиболее удобное использование шаблона хранилища, а именно то, что я могу изменить источник данных для Entity2.php только путем изменения RepositoryA.php, вместо этого беспокоиться о том, кто также мог бы использовать эту сущность.
Если я не разрешу прямой доступ к сущностям, я не смогу выполнять объединения в нескольких репозиториях.

Каков наилучший подход к решению этой проблемы?

3

Решение

Из вашего описания я собираюсь предположить, что ModelA / Repository / RepositoryA.php является конкретной реализацией.
Если я правильно понимаю ваш вопрос, вы также хотите иметь ModelB / Repository / RepositorA.php, оба из которых обращаются к одной и той же таблице (базам) базы данных, чтобы предоставить одну и ту же сущность (скажем, ModelA / Entity / EntityA.php).

Одна вещь, которую вы можете сделать, это превратить оба этих класса RepositoryA в интерфейсы, которые вы затем реализуете в другом месте с помощью одного конкретного класса, что-то вроде этого:

ModelA
|- Entity
|- Entity1.php
|- Entity2.php
|- Entity3.php
|- Repository
|- RepositoryA.php (interface, for dealing with ModelA\Entity\Entity1)
|- Service
|- ServiceA.php (depends on ModelA\Repository\RepositoryA)
ModelB
|- Repository
|- RepositoryB.php (interface, for dealing with ModelA\Entity\Entity1)
|- Service
|- ServiceB.php (depends on ModelB\Repository\RepositoryB)
Infrastructure
|- Repository
|- ConcreteEntity1Repository (concrete class that implements both RepositoryA and RepositoryB interfaces.  Somehow, an instance of this is passed to both ServiceA and ServiceB (dependancy injection or whatever you like))

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

При таком подходе вы эффективно используете один и тот же репозиторий внутри обеих моделей, но без создания какой-либо связи между ними. В зависимости от архитектуры вашей системы, это может быть довольно сложно настроить таким образом, и это может быть излишним для ситуации.

Альтернативный подход может состоять в том, чтобы не делать RepositoryA и RepositoryB интерфейсом, а превратить их в конкретные классы, которые делегируют свою работу, либо передав им общий «Entity1Repository» (и имея RepositoryA и RepositoryB обернуть необходимые вызовы), либо создавая абстрактный базовый класс, который они оба расширяют и который содержит какую-либо общую функциональность.

Это дает дополнительное преимущество, заключающееся в том, что вы также можете добавлять вещи, характерные для одной модели, не будучи частью другой модели. (Например, ModelA \ Repository \ RepositoryA может иметь функцию findRelatedTo (Entity3 $ entity3), не заставляя ModelB знать, что такое Entity3.)

3

Другие решения

У меня есть подобное требование с одним из моих проектов. Я пошел с созданием базового класса, который репозитории могут расширяться так же, как одно из решений Jory Geert. Вот пример стартового проекта Я создал с использованием Phalcon 2.0 с Doctrine 2. Реализация еще не так чиста, и документация все еще находится в стадии разработки, но она должна дать вам представление.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector