views:

59

answers:

3

Suppose there is a interface Subject.

interface Subject { void request(); }

We have a RealSubject class. Suppose we want to enhance RealSubject, we can either use Proxy pattern that wraps around a RealSubject:

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

or we can extends RealSubject and override the method

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

Which approach is better? I'm aware of Liskov principle; let's suppose that EnhancedSubject satisfies the Liskov principle. Do you still consider inheritance?

If there is no interface Subject (i.e., RealSubject doesn't implement any interface), it seems "inherit and override" is the only option as there is no interface to implement in Proxy pattern. Can you still apply Proxy pattern if there is no Subject interface?

A: 

In case RealSubject is expensive to instantiate, proxy pattern is a viable way to go. Otherwise, inheritance might sound fine in some situations.

Adeel Ansari
+1  A: 

The advantage of the proxy / decorator is that it can be reused with derived classes. This can seperate the proxy from the implementation of the class. (You'll have to forgive me if I write invalid java.. it's been a while)

In this case you'd probably write something like:

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

Now you can do

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

If this is overkill for the extension you want, then you should use simple inhertance and overriding.

Michael Anderson
`ref` is private so you can't do that. However, as you already asked for excuse, its perfect. Here, IMO, its not a good idea to make `ref` mutable. ANd BTW, it doesn't seem proxy anymore. What say you?
Adeel Ansari
@Adeel Ansari - agreed, I'd probably take ref as part of my constructor instead. And this implementation is closer to a traditional decorator pattern. Proxy pattern is (in my opinion) part way between the decorator and a bridge patterns.
Michael Anderson
+1  A: 

In response to your first question, "which approach is better"?

I'd personally prefer using the Interface and Proxy (or Decorator) pattern to implement something like this. (See: Item 16: Favor composition over inheritance of Effective Java (2nd Edition))

If the superclass (RealSubject) is not under your control, i.e. in the same package, and specifically designed and documented for Extension, any changes to it's implementation from version to version may break your implementation of the subclass (EnhancedSubject). Essentially what I'm saying is: Depending directly on a concrete implementation leads to fragile code.

In response to your second question, "If EnhancedSubject satisfies the Liskov principle, Do you still consider Inheritance?"

Once again it is safe to use inheritance if the RealSubject and EnhancedSubject are under your control and released with the same life cycle, but Depending directly on a concrete implementation leads to fragile code.

Another point that hopefully sways you towards using the Interface implemenation is Unit Testing.

For Example, Using the case that you would want to apply Unit Testing, it would be a lot easier to inject a mock dependency of RealSubject into your Proxy implementation of Subject so that you can specifically test the Proxy class, rather than have to completely test the whole object hierarchy, RealSubject and EnhancedSubject, just to confirm that EnhancedSubject behaves as expected.

I suppose it can be said though, that if it's all a very simple API and it will not change hardly at in future, Concrete implementations are simply simpler. And Keep It Simple Stupid (K.I.S.S.) is one of the best policies.

"Can you still apply Proxy pattern if there is no Subject interface?" You could inject RealSubject into another class and use RealSubject internally, but if the API using RealSubject depends directly on the concrete class, you have no other choice, but to use Inheritance.

edwardTheGreat