Decorator реализующий интерфейс, а не конкретный класс, возможно ли?

Помогите разрулить зависимости. Итак, допустим у нас есть некий интерфейс Repository:
interface Repository
{
   public function create();
   public function update();
   public function save();
}

Есть абстрактный класс реализующий этот интерфейс:
abstract class UsersRepository implements Repository
{
...
}

И есть конкретный репозиторий, работающий с БД
class DBUsersRepository extends UsersRepository
{
 ...
}

Причем реализация написана таким образом, что ф-ии creatе() и update() связаны с save() - она общая.
Дальше в приложении появляется логика валидации, внедрение которой как раз и хочется сделать через Декоратор. В случае если класс Декоратора наследовать от DBUsersRepository - проблем никак нет. Но этот Декоратор должен быть общим для всех репозиториев независимо от конкретной реализации:
class ValidationRepository implements Repository
{
   protected $repository;
   protected $validator;

   public function __construct(Repository $repository) 
   {
      $this->repository = $repository;
   }

   public function setValidator(Validator $validator)
   {
       $this->validator = $validator;
       return $this;
   }

   public function save($model)
   {
       if($this->validator->validate($model)){
           return $this->repository->save($model); 
      }
   }
}

Как видно декоратор расширяет только один метод интерфейса. Отсюда вопрос, что делать с остальными? Они должны быть и работать должны аналогично принимаемого $repository, но в собственном контексте. Чтобы клиентский код:
$rep = new ValidationRepository( new DBUsersRepository());
    $rep->setValidator($validator);
    $rep->create($modelsData); //create() должен вызваться из UsersRepository, а функция save() в нем - уже из ValidationRepository

Отрабатывал корректно.
  • Вопрос задан
  • 326 просмотров
Пригласить эксперта
Ответы на вопрос 1
@Mercury13
Программист на «си с крестами» и не только
Так, проблему понял (извините, больной слегка, соображаю плохо).

Перед нами явно ломаная абстракция: нам надо глубоко внедряться в объект. Тут одно из двух.
1) Бить объект на два, Repository с create() и update(), и DataStorage с save(). Тогда прослойкой между этими объектами можно пристроить валидатор.
2) Налаживать точку для подключения внешнего валидатора в save().

P.S. Декоратор и должен реализовать интерфейс, однако набор возможностей, которые он может делать с этим интерфейсом, невелик.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы