Прокси-шаблон против переопределения - PullRequest
3 голосов
/ 19 октября 2010

Предположим, есть интерфейс Тема.

interface Subject { void request(); }

У нас есть класс RealSubject.Предположим, что мы хотим улучшить RealSubject, мы можем либо использовать шаблон Proxy, который обертывает RealSubject:

class Proxy implements Subject { 
   private RealSubject ref;
   void request(){ ... }
}

, либо мы можем расширить RealSubject и переопределить метод

class EnhancedSubject extends RealSubject {
   @Override
   void request() { ... }
}

Какой подход лучше?Я знаю принцип Лискова;давайте предположим, что EnhancedSubject удовлетворяет принципу Лискова.Вы все еще рассматриваете наследование?

Если нет субъекта интерфейса (т. Е. RealSubject не реализует какой-либо интерфейс), кажется, что «наследовать и переопределять» - это единственный вариант, поскольку в Proxy нет интерфейса для реализации.шаблон.Можно ли по-прежнему применять шаблон Proxy, если нет интерфейса Subject?

Ответы [ 2 ]

6 голосов
/ 19 октября 2010

В ответ на ваш первый вопрос: « какой подход лучше »?

Я лично предпочел бы использовать шаблон Interface и Proxy (или Decorator) для реализации чего-то подобного.(См. Пункт 16: Композиция Favour по наследованию Effective Java (2nd Edition) )

Если суперкласс (RealSubject) не находится под вашим контролем, т.е. в том же пакете,и специально разработанные и документированные для Extension любые изменения его реализации от версии к версии могут нарушить вашу реализацию подкласса (EnhancedSubject).По сути, я говорю следующее: Прямая зависимость от конкретной реализации приводит к хрупкому коду.

В ответ на ваш второй вопрос: " Если EnhancedSubject удовлетворяет принципу Лискова, Вы все еще рассматриваете Наследование?"

Еще раз безопасно использовать наследование, если RealSubject и EnhancedSubject находятся под вашим контролем и выпущены с тем же жизненным циклом, но Непосредственная зависимость от конкретной реализации приводит к хрупкому коду.

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

Например, в том случае, если вы хотитеЕсли вы хотите применить модульное тестирование, было бы намного проще внедрить ложную зависимость RealSubject в вашу Proxy реализацию Subject, чтобы вы могли специально протестировать класс Proxy, вместо того, чтобы полностью тестироватьвся иерархия объектов, RealSubject и EnhancedSubject, просто для подтверждения того, что EnhancedSubject ведет себя как ожидалось.

Полагаю, это можно сказатьтем не менее, если это очень простой API, и он вряд ли изменится в будущем, конкретные реализации будут просто на проще .And Keep It Simple Stupid (KISS) - одна из лучших политик.

" Можно ли по-прежнему применять шаблон Proxy, если нет интерфейса субъекта? " Вы можете добавить RealSubject в другойКласс и использовать RealSubject для внутреннего использования, но если API, использующий RealSubject, напрямую зависит от конкретного класса, у вас нет другого выбора, кроме как использовать Inheritance.

1 голос
/ 19 октября 2010

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

В этом случае вы, вероятно, напишите что-то вроде:

class LoggingSubjectProxy implements Subject
{
   private Subject ref;
   void request() 
   { 
      log("Called request");
      ref.request();
   }
}

Теперь вы можете

LoggingSubjectProxy l;
if(dosimple)
{
    l.ref = SimpleSubject();
}
else
{
    l.ref = ComplexSubject();
}
l.request()

Если это расширение для нужного вам расширения, вам следует использовать простое наследование и переопределение.

...