Say I have a class with many of public methods:
public class MyClass {
public void method1() {}
public void method2() {}
(...)
public void methodN() {}
}
Now I would like to create a wrapper class which would delegate all the methods to wrapped instance (delegate):
public class WrapperClass extends MyClass {
private final MyClass delegate;
public WrapperClass(MyClass delegate) {
this.delagate = delegate;
}
public void method1() { delegate.method1(); }
public void method2() { delegate.method2(); }
(...)
public void methodN() { delegate.methodN(); }
}
Now if MyClass has a lot of methods I would need to override each of them which is more or less the same code which just "delegates". I was wondering if it is possible to do some magic to automatically call a method in Java (so the Wrapper class would need to say "Hey if you call a method on me just go to delegate object and call this method on it).
BTW: I can not use inheritance because the delegate is not under my control.I just get its instance from elsewhere (another case would be if MyClass was final).
NOTE: I do not want IDE generation. I know I can do it with help of IntelliJ/Eclipse, but I'm curious if this can be done in code.
Any suggestions how to achieve something like this? (NOTE: I would probably be able to do it in some scripting languages like php where I could use php magic functions to intercept the call).
Perhaps the dynamic
Proxy
of java can help you. It only works if you consequently use interfaces. In this case, I will call the interfaceMyInterface
and set up a default implementation:The wrapper class implementation would look like:
Note that this class:
MyClass
, to inherit a default implementation (any other would do)Invocationhandler
, to allow the proxy to do reflectionMyInterface
(to satisfy the decorator pattern)This solution allows you to override special methods, but to delegate all others. This will even work with sub classes of Wrapper class.
Note that the method
findMethod
does not yet capture the special cases.Credits go to CoronA for Pointing out the Proxy and InvocationHandler classes. I worked out a more reusable utility class based on his solution, using generics:
Test it:
I wanted to create an automatic delegation class that executes the delegatee's methods on the EDT. With this class, you just create a new utility method that will use an EDTDecorator, in which the implementation will wrap
m.invoke
in aSwingUtilities.invokeLater
.However, if I reflect on this, I may want to reconsider making a non-Reflection based proxy per interface that I have - it might be cleaner and faster, and more understandable. But, it's possible.
Define a method in
WrapperClass
i.e.delegate()
that returns the instance ofMyClass
OR
You can use reflection to do that but the caller has to pass the method name as an argument to an exposed method. And there will be complications regarding the method arguments/overloaded methods etc.
The code that you have posted has
public class WrapperClass extends MyClass
Actually your current implementation of
WrapperClass
is actually a decorator on top of MyClassSwitch to Groovy :-)
http://mrhaki.blogspot.com/2009/08/groovy-goodness-delegate-to-simplify.html
You don't have to do this -- your Wrapper class is a subclass of the original class, so it inherits all of its publicly accessible methods -- and if you don't implement them, the original method will be called.
You shouldn't have
extends Myclass
together with a privateMyClass
object -- that's really really redundant, and I can't think of a design pattern where doing that is right. YourWrapperClass
is aMyClass
, and hence you can just use its own fields and methods instead of callingdelegate
.EDIT: In the case of
MyClass
beingfinal
, you'd be circumventing the willfull declaration to not allow subclassing by "faking" inheritance; I can't think of anyone willing to do that other than you, who is in control ofWrapperClass
; but, since you're in control ofWrapperClass
, not wrapping everything you don't need is really more than an option -- it's the right thing to do, because your object is not aMyClass
, and should only behave like one in the cases you mentally considered.EDIT you've just changed your question to mean something completely different by removing the
MyClass
superclass to yourWrapperClass
; that's a bit bad, because it invalidates all answers given so far. You should have opened another question.This question is 6 months old already and @CoronA's wonderful answer has satisfied and been accepted by @walkeros, but I thought I would add something here as I think this can be pushed an extra step.
As discussed with @CoronA in the comments to his answer, instead of having to create and maintain a long list of
MyClass
methods inWrapperClass
(i.e.public void methodN() { delegate.methodN(); }
), the dynamic proxy solution moves this to the interface. The issue is that you still have to create and maintain a long list of signatures for theMyClass
methods in the interface, which is perhaps a bit simpler but doesn't completely solve the problem. This is especially the case if you don't have access toMyClass
in order to know all the methods.According to Three approaches for decorating your code,
So perhaps this is an expected limitation of the Decorator Pattern.
@Mark-Bramnik, however, gives an fascinating solution using CGLIB at Interposing on Java Class Methods (without interfaces). I was able to combine this with @CoronaA's solution in order to create a wrapper that can override individual methods but then pass everything else to the wrapped object without requiring an interface.
Here is
MyClass
.Here is
WrapperClass
which only overridesmethod2()
. As you'll see below, the non-overridden methods are, in fact, not passed to the delegate, which can be a problem.Here is
MyInterceptor
which extendsMyClass
. It employs the proxy solution using CGLIB as described by @Mark-Bramnik. It also employs @CononA's method of determining whether or not to send the method to the wrapper (if it is overridden) or the wrapped object (if it is not).Here is
Main
and the results you get if you run it.As you can see, when you run the methods on
wrapped
you get the wrapper for the methods that are not overridden (i.e.method1()
andmethod3()
). When you run the methods onproxified
, however, all of the methods are run on the wrapped object without the pain of having to delegate them all inWrapperClass
or put all of the method signatures in an interface. Thanks to @CoronA and @Mark-Bramnik for what seems like a pretty cool solution to this problem.