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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With